Skip to content

fix(auth): make _notifyAllSubscribers non-blocking to prevent callback deadlocks#2016

Open
7ttp wants to merge 1 commit intosupabase:masterfrom
7ttp:fix/auth-non-blocking-subscriber-notifications
Open

fix(auth): make _notifyAllSubscribers non-blocking to prevent callback deadlocks#2016
7ttp wants to merge 1 commit intosupabase:masterfrom
7ttp:fix/auth-non-blocking-subscriber-notifications

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)

@7ttp
Copy link
Contributor Author

7ttp commented Feb 11, 2026

hey @mandarini almost forgot about this,
was curious if this aswell is being discussed internally (in the recent lock related discussion) ?
or should i continue with the suggested approaches? 😅💚

@mandarini
Copy link
Contributor

let's park it for now @7ttp ! I want to see how the internal discussion goes!! Thank you for ALL the help!!!!! 💚

@mandarini mandarini self-assigned this Feb 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Supabase Auth-JS Deadlock Issue

4 participants