Problem
When the client detects an Onyx-update gap, the SequentialQueue is paused (via shouldPauseQueue in the SaveResponseInOnyx middleware, or SequentialQueue.pause() in applyOnyxUpdatesReliably/DeferredOnyxUpdates) and is only unpaused once the OnyxUpdateManager finishes resolving the gap. That pause/unpause pair is not balanced by construction — several early-return and failure paths in the async chain (non-leader tab early return in handleMissingOnyxUpdates, a subscription that never re-fires, a dead in-progress fetch promise) leave the queue paused forever. Queued write commands like OpenApp then never execute, IS_LOADING_APP never clears, and the user is stuck on a full-screen skeleton on every page until a hard page refresh; reads park forever on waitForIdle(). This was reproduced deterministically by switching priority mode from #focus to normal, which left OpenApp and PusherPing stuck with [SequentialQueue] Unable to flush. Queue is paused. repeating indefinitely, and it matches user reports of intermittent "infinite skeleton" sessions lasting 10+ minutes that only resolve by resetting client state.
Solution
Add a pause watchdog inside SequentialQueue, which owns isQueuePaused. pause() arms a timeout (CONST.NETWORK.MAX_PAUSE_WATCHDOG_TIME_MS, 60s) and unpause()/resetQueue() clear it. A connectWithoutView subscription to ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT re-arms the watchdog on every applied-update advance while paused, so a genuinely progressing (even slow) catch-up never trips it — only a pause with zero progress for the full window does. When it fires, it emits a Log.alert so residual root causes stay visible in telemetry, then force-calls unpause(), which flushes the queue and re-runs the stuck OpenApp/ReconnectApp to re-sync the client and clear the skeleton. This is a liveness safety net rather than a root-cause fix for each individual orphaning path: it converts every "stuck forever until refresh" variant into a bounded ≤60s stall that self-heals.
PR
#97228
Issue Owner
Current Issue Owner: @abzokhattab
Problem
When the client detects an Onyx-update gap, the
SequentialQueueis paused (viashouldPauseQueuein the SaveResponseInOnyx middleware, orSequentialQueue.pause()inapplyOnyxUpdatesReliably/DeferredOnyxUpdates) and is only unpaused once the OnyxUpdateManager finishes resolving the gap. That pause/unpause pair is not balanced by construction — several early-return and failure paths in the async chain (non-leader tab early return inhandleMissingOnyxUpdates, a subscription that never re-fires, a dead in-progress fetch promise) leave the queue paused forever. Queued write commands likeOpenAppthen never execute,IS_LOADING_APPnever clears, and the user is stuck on a full-screen skeleton on every page until a hard page refresh; reads park forever onwaitForIdle(). This was reproduced deterministically by switching priority mode from #focus to normal, which leftOpenAppandPusherPingstuck with[SequentialQueue] Unable to flush. Queue is paused.repeating indefinitely, and it matches user reports of intermittent "infinite skeleton" sessions lasting 10+ minutes that only resolve by resetting client state.Solution
Add a pause watchdog inside
SequentialQueue, which ownsisQueuePaused.pause()arms a timeout (CONST.NETWORK.MAX_PAUSE_WATCHDOG_TIME_MS, 60s) andunpause()/resetQueue()clear it. AconnectWithoutViewsubscription toONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENTre-arms the watchdog on every applied-update advance while paused, so a genuinely progressing (even slow) catch-up never trips it — only a pause with zero progress for the full window does. When it fires, it emits aLog.alertso residual root causes stay visible in telemetry, then force-callsunpause(), which flushes the queue and re-runs the stuckOpenApp/ReconnectAppto re-sync the client and clear the skeleton. This is a liveness safety net rather than a root-cause fix for each individual orphaning path: it converts every "stuck forever until refresh" variant into a bounded ≤60s stall that self-heals.PR
#97228
Issue Owner
Current Issue Owner: @abzokhattab