docs/long-term-plans/ios-dropbox-sync-reliability.md
Status: Investigation Complete — Fixes Pending
Issue: #6333 Severity: High — Dropbox sync is completely broken for some iOS users
Dropbox sync consistently fails on iOS with -1005 "The network connection was lost", while the web app works fine on the same device. Multiple users have confirmed the issue across different iOS versions and SP releases.
URLSession.sharedCapacitor's iOS HTTP handler (CapacitorUrlRequest.swift) routes all requests through URLSession.shared — a singleton that:
When connections go stale (from app backgrounding, server-side connection resets, or HTTP/2 lifecycle), URLSession.shared tries to reuse the dead connections, causing -1005.
Evidence from logs: First download succeeds, second download 19 seconds later fails with -1005 — classic stale connection reuse pattern.
Why web works: Browser fetch() runs through WKWebView's own networking stack, which handles reconnection more gracefully.
URLSession.shared reuses it[NSURLSession sharedSession] may not be invalidatedURLSession.sharedUse patch-package to modify CapacitorUrlRequest.swift:
// Before (Capacitor 7.4.3+)
open func getUrlSession(_ call: CAPPluginCall) -> URLSession {
let disableRedirects = call.getBool("disableRedirects") ?? false
if !disableRedirects {
return URLSession.shared
}
return URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: nil)
}
// After
open func getUrlSession(_ call: CAPPluginCall) -> URLSession {
let disableRedirects = call.getBool("disableRedirects") ?? false
let config = URLSessionConfiguration.ephemeral
if !disableRedirects {
return URLSession(configuration: config)
}
return URLSession(configuration: config, delegate: self, delegateQueue: nil)
}
Tradeoffs:
Note: Capacitor 8 does NOT fix this — URLSession.shared usage is identical in v8.
Capacitor's Swift code: let timeout = (connectTimeout ?? readTimeout ?? 600000.0) / 1000.0
Our code passes both connectTimeout: 30000 and readTimeout: 120000. Since connectTimeout is set, readTimeout is silently ignored. All data transfers get a 30s timeout instead of the intended 120s.
Fix: Stop passing connectTimeout from native-http-retry.ts, or pass a single combined timeout.
Current delays: 1s, 2s. Stale connections need more time to flush.
Fix: Increase to 3s, 6s (or similar). Consider whether MAX_RETRIES should also increase.
Use Capacitor's App.addListener('appStateChange') to detect foreground resume and add a brief delay (500ms-1s) before allowing sync requests.
Use @capawesome/capacitor-background-task to request ~30s of background execution time during sync, preventing iOS from suspending the app mid-operation.
patch-package setup for iOS native code