Skip to content

Conversation

@7ttp
Copy link
Contributor

@7ttp 7ttp commented Jan 12, 2026

Summary

Makes _notifyAllSubscribers non-blocking by removing await on subscriber callbacks. This prevents deadlocks when callbacks perform async operations that require the auth lock.

Problem

When a subscriber callback in onAuthStateChange performs async operations like getUser() or getSession(), a deadlock occurs:

  1. Auth method (e.g., signInWithPassword) acquires lock via _acquireLock()
  2. Inside the lock, it calls await _notifyAllSubscribers() which awaits all callbacks
  3. Subscriber callback calls getUser() which tries to acquire the same lock
  4. Lock queues getUser() to wait for current operation
  5. Current operation waits for callback to complete
  6. Deadlock: callback waits for getUser() → waits for lock → waits for callback

Solution

Remove async/await from _notifyAllSubscribers. Callbacks fire synchronously, async callbacks run in background without blocking. Errors still caught and logged.

Related

@7ttp 7ttp requested review from a team as code owners January 12, 2026 15:00
@coveralls
Copy link

Coverage Status

coverage: 81.017% (+0.02%) from 80.997%
when pulling 60e2a3d on 7ttp:fix/auth-non-blocking-subscriber-notifications
into 09aa106 on supabase:master.

@simplysparsh
Copy link

@7ttp Thanks for the PR
@mandarini @grdsdev Would be great if you can review this.

@mandarini
Copy link
Contributor

mandarini commented Jan 21, 2026

This PR will re-introduce the SSR OAuth bug that #2039 fixes.

The SSR callback is async:

  client.auth.onAuthStateChange(async (event) => {                                       
    await applyServerStorage({...})                                                      
  })                                                                                     

With this PRs non-blocking approach, applyServerStorage won't complete before serverless functions return, causing the same cookie-setting failure as the original setTimeout issue.

We need a different solution that:

  1. Prevents deadlocks when callbacks call getUser() or getSession()
  2. Ensures critical async operations (like cookie-setting) complete before returning
  3. Works in both serverless and long-running server contexts

Potential approaches:

  • Detect if callback is async and warn/error if it awaits other auth methods
  • Document that callbacks MUST NOT await auth methods
  • Refactor locking mechanism to allow reentrant calls during notifications
  • Make cookie-setting synchronous (queue writes instead of awaiting)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

4 participants