Skip to content

fix(realtime): patch channel join payloads with resolved access token before flushing send buffer#2136

Merged
mandarini merged 1 commit intomasterfrom
fix/realtime-async-token-race-condition
Feb 25, 2026
Merged

fix(realtime): patch channel join payloads with resolved access token before flushing send buffer#2136
mandarini merged 1 commit intomasterfrom
fix/realtime-async-token-race-condition

Conversation

@mandarini
Copy link
Contributor

@mandarini mandarini commented Feb 25, 2026

What is the current behavior?

On React Native / Expo, the auth accessToken callback reads from async storage (e.g. expo-secure-store). When subscribe() is called before the token has resolved, the phx_join payload is captured with no access_token. The stale join message is buffered, and when _onConnOpen() fires it flushes the buffer — sending the token-less join to the server.

The server accepts the join but cannot evaluate RLS policies without a token, so postgres_changes events are silently filtered out. The channel appears subscribed but no data arrives.

On browsers this never happens because localStorage.getItem() is synchronous, so the token is always available when subscribe() snapshots the join payload.

Fixes #1461
Related: #1477, #1725

What is the new behavior?

In _onConnOpen(), after the auth promise resolves:

  1. Patch each channel's joinPush payload with the now-available accessTokenValue
  2. Clear stale buffered join messages (they captured the old token-less payload in a closure)
  3. Re-send the join for channels still in joining state

On browsers this is a no-op — the token was already present at subscribe() time.

@github-actions github-actions bot added the realtime-js Related to the realtime-js library. label Feb 25, 2026
@mandarini mandarini self-assigned this Feb 25, 2026
@mandarini mandarini marked this pull request as ready for review February 25, 2026 12:06
@mandarini mandarini requested review from a team as code owners February 25, 2026 12:06
@pkg-pr-new
Copy link

pkg-pr-new bot commented Feb 25, 2026

Open in StackBlitz

@supabase/auth-js

npm i https://pkg.pr.new/@supabase/auth-js@2136

@supabase/functions-js

npm i https://pkg.pr.new/@supabase/functions-js@2136

@supabase/postgrest-js

npm i https://pkg.pr.new/@supabase/postgrest-js@2136

@supabase/realtime-js

npm i https://pkg.pr.new/@supabase/realtime-js@2136

@supabase/storage-js

npm i https://pkg.pr.new/@supabase/storage-js@2136

@supabase/supabase-js

npm i https://pkg.pr.new/@supabase/supabase-js@2136

commit: a2b6a5c

@mandarini mandarini merged commit c35fba4 into master Feb 25, 2026
18 of 19 checks passed
@mandarini mandarini deleted the fix/realtime-async-token-race-condition branch February 25, 2026 12:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

realtime-js Related to the realtime-js library.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2.49.9 breaks postgres_change realtime feature with expo (react-native)

2 participants