Skip to content

[Web/Capacitor] Sync stream stays wedged after long iOS background; connect() is a no-op, only disconnect-first recovers #1077

Description

@sprinter-bot

Environment: @powersync/web 2.2.0, @powersync/capacitor 0.8.2, @powersync/common 2.1.0, powersync-sqlite-core 0.5.3, Capacitor 8, iOS (physical device + simulator).

Summary

After a long iOS background/suspension (hours), on foreground the sync stream is wedged: SyncStatus reports connected: false, connecting: false, downloadError: "Load failed", with CRUD stuck in the upload queue. Auth is fine — the JWT is valid and refreshed. db.connect() does not recover it. Only db.disconnect() then db.connect(), or a full app restart (force-quit), brings the stream back.

Repro (fast)

Turn airplane mode on ~10s (the stream errors Load failed), then off; or background the app for a long stretch. On resume, connect() alone does not re-dial.

Expected

On (re)connect, the SDK detects the dead/stale socket and re-establishes it — as was done for React Native in PR #607 ("iOS WebSockets could fail to reconnect after a connection issue", v1.35.7).

Actual

connect() returns without re-dialling because the engine still believes its streaming implementation is live-or-connecting across the suspension; the stream stays down with a valid token and a stuck upload queue.

Our workaround

disconnect()-first then connect(), driven from a Capacitor appStateChange foreground handler plus a 60s watchdog — because the web engine doesn't observe app lifecycle (no visibilitychange/AppState hook), so nothing tells it to re-check on resume.

Questions

  1. Is the RN PR Improve Connection Locks #607 fix (stale-socket detection on reconnect) planned or available for @powersync/web / @powersync/capacitor?
  2. Should the Capacitor SDK hook app lifecycle (foreground → reconnect), or is that intended to remain the host app's responsibility?
  3. Is there a supported "hard reconnect" API beyond disconnect() + connect()?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions