Skip to content

fix(auth,supabase): recover from client corruption after tab suspension#2228

Open
KrunchMuffin wants to merge 1 commit intosupabase:masterfrom
KrunchMuffin:fix/tab-suspension-client-corruption
Open

fix(auth,supabase): recover from client corruption after tab suspension#2228
KrunchMuffin wants to merge 1 commit intosupabase:masterfrom
KrunchMuffin:fix/tab-suspension-client-corruption

Conversation

@KrunchMuffin
Copy link
Copy Markdown

Summary

Fixes the Supabase client becoming irrecoverably corrupted after browser tab suspension (2-5+ minutes), which affects PWAs, mobile browsers, and long-lived sessions. After resuming:

  • auth.getSession() could return null despite a valid session in storage
  • functions.invoke() could hang indefinitely (blocked on lock-gated getSession)
  • Realtime channels failed silently with stale tokens and no reconnection

Root cause: When _recoverAndRefresh fails with a retryable error (e.g. network still reconnecting after tab resume), no auth event was emitted, leaving realtime and functions permanently desynchronized. The next auto-refresh tick could be up to 30 seconds away.

Changes

auth-js (GoTrueClient):

  • Emit SIGNED_IN with current session on retryable refresh failure so downstream listeners (realtime, functions) can re-sync immediately instead of silently dropping the error
  • Trigger an immediate _autoRefreshTokenTick() after visibility change recovery instead of waiting up to AUTO_REFRESH_TICK_DURATION_MS (30s) for the next scheduled tick

supabase-js (SupabaseClient):

  • Add visibilitychange listener that force-syncs a fresh token to the realtime client when the tab resumes — acts as a safety net for cases where the auth event bridge misses the token update

Test plan

  • New unit test: should sync fresh token to realtime on visibility change (tab resume) in SupabaseClient tests
  • All existing realtime-js tests pass (325/325, only pre-existing worker test failures on non-browser env)
  • All existing supabase-js unit tests pass (88/88)
  • Manual testing: open app with realtime channel, background tab for 3-5 min, resume and verify session + realtime recover

Related

Closes supabase/supabase#36046

🤖 Generated with Claude Code

After a browser tab is suspended for several minutes (common in PWAs,
mobile browsers, and Safari), the Supabase client could enter an
irrecoverable corrupted state where auth.getSession() returns null,
functions.invoke() hangs, and realtime channels fail silently.

Root cause: when _recoverAndRefresh fails with a retryable error (e.g.
network still reconnecting after tab resume), no auth event was emitted,
leaving realtime and functions with a stale/expired token. Additionally,
the next auto-refresh tick could be up to 30 seconds away.

Changes:

**auth-js (GoTrueClient):**
- Emit SIGNED_IN with current session on retryable refresh failure so
  downstream listeners (realtime, functions) can re-sync immediately
- Trigger an immediate auto-refresh tick after visibility change recovery
  instead of waiting up to 30s for the next scheduled tick

**supabase-js (SupabaseClient):**
- Add visibilitychange listener that force-syncs a fresh token to the
  realtime client when the tab resumes, as a safety net for cases where
  the auth event bridge misses the token update

Closes supabase/supabase#36046

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@gfsaaser24
Copy link
Copy Markdown

This looks solid. Nice work dude.

@mandarini
Copy link
Copy Markdown
Contributor

The reason why I do not want to merge this PR (or similar PRs) is that they are patching a deeper issue with how we use the Web Lock API and navigator locks. We have discussed this internally with the team quite a lot. While we appreciate all your contributions, we do want to come up with a solution to the root of the problem.
Would you like to try out 2.103.1-beta.0? It's a release for this PR #2235.

@mandarini mandarini added the do-not-merge Do not merge this PR. label Apr 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

do-not-merge Do not merge this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Supabase Client Becomes Irrecoverably Corrupted After Tab Suspension (PWA/Browser)

3 participants