Mobile

iOS app multipart upload restarts from zero when switching between 5G and Wi‑Fi during transfer (React Native background uploader)

Environment

Environment

React Native app running on iPhone 14 Pro (iOS 17.2). Uploads use a JS-managed background queue with native NSURLSessionUploadTask (NSURLSessionBackgroundConfiguration). Server accepts chunked multipart uploads with Range headers and supports resumable offsets.

Symptoms

Symptoms

When a user starts a large file upload on 5G and moves into Wi‑Fi range (or vice versa), the uploader restarts from 0% rather than resuming at the last byte. The app logs show a new upload task created and the server receiving a fresh POST instead of a range continuation. This occurs unpredictably during a network handoff; small uploads unaffected.

Observations

Observations

Console logs show the original NSURLSession background task transitions to 'completed' with an error indicating 'network connection lost' at the same instant a new task is scheduled by the JS layer. The server shows a short-lived connection followed by a separate new connection with no 'Range' or 'Upload-Offset' header. Testing with a native iOS sample app using background NSURLSessionResumeData successfully resumes on handoff, indicating server-side resume works and that background resume behavior differs between native and RN wrapper implementation.

Already attempted

Already attempted

Wrapped upload in a persistent native module bridging RN -> native NSURLSession (migrated from pure JS), but still saw restarts when the RN JS engine process was suspended or terminated. Enabled background modes and ensured proper application:didFinishLaunchingWithOptions: and delegates are present. Attempted to persist resume data to disk on URLSession:task:didCompleteWithError: but observed resumeData is nil when task is cancelled by OS during handoff.

Question

Question

What causes background NSURLSession uploads to restart from zero specifically during cellular/Wi‑Fi handoffs in a React Native app, and what practical changes can ensure resumable transfers without requiring users to remain on a single network?

COMMUNITY RESPONSES

Verified community troubleshooting

0 replies

No answers yet..

Showing 0 of 0 community responses
AI DIAGNOSTICS

Incident analysis

Updated 2d ago• Trouble ID

Most likely causes

Upload implementation relies on JS-managed state instead of native NSURLSession background delegates; resumeData is never persisted to disk. 90%
React Native bridge or JS runtime suspension during network handoff prevents capture/storage of NSURLSession resumeData. 85%
OS cancels task without providing resumeData when delegate callbacks are not installed at native layer or when session is misconfigured. 60%

Summary

The root cause is that during a network handoff the OS may cancel or invalidate the background NSURLSession task and only supply resumable resumeData to the app if the app's native background delegate is reliably invoked. In RN apps the JS engine and bridge can be suspended or killed during handoff; if resumeData handling or persistence is implemented in JS (or not wired into native session delegates), the ability to resume is lost and the app starts a fresh upload. Native sample apps succeed because the delegate and resumeData handling are fully native and run even when the JS runtime is paused.

Suggested Fixes

Diagnostic step 1
Move resume handling fully to native iOS: implement NSURLSession background configuration with native delegates that persist resumeData to file storage immediately on task completion/failure.
Diagnostic step 2
Ensure native delegate code runs standalone from RN JS (no reliance on bridge) so resumeData is saved even if JS is suspended. Add logs to verify delegate invoked during handoff.
Diagnostic step 3
Test handoff scenarios with a minimal native app reproducer to confirm iOS behavior, then mirror the native flow in RN bridge code.

Continue troubleshooting

Matched from the title, description and tags