Skip to content

iOS: reject instead of crashing when an upload's file is missing - #48

Merged
dmurphy5 merged 1 commit into
masterfrom
dylan/ios-missing-file-no-crash
Sep 29, 2026
Merged

dmurphy5 merged 1 commit into
masterfrom
dylan/ios-missing-file-no-crash

Conversation

@dmurphy5

@dmurphy5 dmurphy5 commented Sep 28, 2026 •

Copy link
Copy Markdown

This is a fix for the current version, not v10

On iOS, uploadTask(with:fromFile:) on a background session throws an Objective-C exception when it cannot read the file. Swift cannot catch that exception, so the app dies. In Diana this is Sentry DIANA-19VW: about 2,500 crashes from 1,700 users since August. It usually happens at launch. The app checks that the file exists, and then a finished upload deletes that file before iOS opens it.

This change wraps the call in a small Objective-C helper that catches the exception and returns it to Swift as an error.

Before: a missing file ends the app.
After: startUpload rejects with "Cannot read file at …". Any concurrent calls with the same id get the same rejection. A chunked part that cannot be enqueued stalls with errorKind: 'file'.

What to look at

  • The podspec. RNBGUCatchException.h is now the one public header, so Swift can see it through the module umbrella. It imports only Foundation, so a plain Obj-C @import react_native_background_upload; still compiles.
  • startUpload in RNBackgroundUpload.swift. Parked same-id calls now store both resolve and reject, so a failure reaches all of them.

Decisions and trade-offs

  • A chunked part that fails to enqueue stalls. A failed part-file build is handled the same way. The upload keeps its bytes, and the next startUpload resumes it.
  • The rejection uses the existing "RN Uploader" code. The thrown error is NSURLErrorCannotOpenFile, so errorKind(for:) classifies it as 'file'.
  • Version 9.0.1 is set, but no tag is created. Tagging happens at release.

Test Plan

  • A standalone macOS program created a background session and uploaded a missing file. It raised "NSInvalidArgumentException: Cannot read file at …", which matches the Sentry event. With the helper the exception was caught. Without it the process terminated.
  • All iOS Swift sources type-check against the iOS 15.1 SDK, with React's two promise typedefs stubbed. Unmodified master also passes this check.
  • yarn lint-root, yarn typecheck and yarn test pass with 37 tests.
  • Not verified: a real CocoaPods build and a device run. Pod install must pick up the two new files and put the public header in the umbrella.

🤖 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 a file deleted between the caller's existence check and the
task creation ended the app.

An Objective-C helper now catches the exception. startUpload rejects,
including the concurrent same-id calls parked on the first one. A chunked
part that cannot be enqueued stalls with errorKind 'file'.

Fixes DIANA-19VW.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dmurphy5
dmurphy5 merged commit fa02688 into master Sep 29, 2026
2 checks passed
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