Skip to content

v10: survive a file the iOS session cannot read - #49

Open
dmurphy5 wants to merge 1 commit into
dylan/v10-6-wifi-pausefrom
dylan/v10-7-ios-unreadable-file
Open

dmurphy5 wants to merge 1 commit into
dylan/v10-6-wifi-pausefrom
dylan/v10-7-ios-unreadable-file

Conversation

@dmurphy5

@dmurphy5 dmurphy5 commented Sep 28, 2026 •

Copy link
Copy Markdown

On iOS, uploadTask(with:fromFile:) on a background session throws an Objective-C exception when it cannot read the file. Swift cannot catch it, so the app dies. That is the Diana crash fixed on master in #48. This PR brings the same guard to the v10 transport.

v10 is not exposed to the race that causes the Diana crash. It stages every body in its own folder and deletes staged files only on the coordinator queue, and it checks the body right before creating the task. The guard still matters, because any unreadable file ends the app, whatever the cause. It also keeps the helper from 9.0.1 in use once v10 is rebased onto master.

Before: an unreadable file ends the app.
After: the attempt gets no task.

  • Simple entry. It settles file only when the staged body is gone. If the body is still there, the entry goes back to queued and is issued again after a backoff. This is the same rule as a file error at completion.
  • Chunked part. It refills later, like a failed part build.

What to look at

  • The catch in issue in QueueCoordinator+Simple.swift. The retry goes through deferIssue, not scheduleRetry. scheduleRetry would create the delayed task at once, fail the same way, and recurse.
  • Transport.upload now throws. The fake transport has a beforeUpload hook, so tests can throw or delete the file just before the task is created.

Decisions and trade-offs

  • The helper files match master byte for byte. When v10 is rebased onto master, the two new files merge without a conflict. RNBackgroundUpload.swift will still conflict there, because v10 rewrote it. Keep v10's side.
  • The podspec change matches master. RNBGUCatchException.h is the only public header, and it imports only Foundation.
  • The promote PR does not include this layer. Its head is dylan/v10-6-wifi-pause. It needs to be retargeted or recreated before it can ship this change.

Test Plan

  • cd ios && swift test passes all 204 tests. Three are new:
    • An unreadable body at issue creates no task and issues again after the backoff.
    • A body deleted as its task is created settles file.
    • An unreadable part file refills after the backoff.
  • The pod's Swift sources type-check against the iOS 15.1 SDK, with React's promise typedefs stubbed. The branch below this one also passes that check.
  • yarn lint-root, yarn typecheck and yarn test pass with 189 tests.
  • Not verified: a CocoaPods build and a device run.

🤖 Generated with Claude Code

A background URLSession raises an NSInvalidArgumentException, not an
error, when uploadTask(with:fromFile:) cannot read the file. Swift cannot
catch it, so it ends the app.

The session transport now catches it with the same Objective-C helper as
the 9.0.1 fix and throws. A simple attempt settles 'file' only when its
staged body is gone, and otherwise issues again after a backoff. A chunked
part refills later, like a failed part build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dmurphy5
dmurphy5 added this pull request to stack #44 September 28, 2026 20:53
@dmurphy5 dmurphy5 changed the title dylan/v10 7 ios unreadable file v10: survive a file the iOS session cannot read Sep 28, 2026
@dmurphy5
dmurphy5 marked this pull request as ready for review September 29, 2026 15:19
@dmurphy5
dmurphy5 requested a review from elliottkember October 1, 2026 18:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants