Skip to content

[Auth] GoTrueClient uses infinite timeouts for lock acquisition causing deadlocks in production #1594

@dtinth

Description

@dtinth

Bug report

  • I confirm this is a bug with Supabase, not with my own application.
  • I confirm I have searched the Docs, GitHub Discussions, and Discord.

Describe the bug

I encountered a situation where Supabase Auth never finish initializing.

  • The impact on my app is that it never finishes initializing and any auth operation hangs.

  • I already checked that onAuthStateChange is not async and doesn't call any Supabase API, so #762 doesn't apply.

  • The GoTrueClient initialization hangs indefinitely on some devices (in my case, Chrome Android) due to a lack of timeouts in the Web Locks API implementation.

  • I investigated this by digging into the source code and enabling the undocumented debug option. On the affected device, the #_acquireLock call never resolved

    On a working device, the debug log is normal On a problematic device, it got stuck at #_acquireLock
    Image Image

    Additionally, on a problematic device, checking supabase.auth.initializePromise returns a never-resolving promise.

  • It seems that a previous lock wasn't properly released… when I run await navigator.locks.query() I see that some locks are being held indefinitely.

    Held locks
    Image
  • Is it really a good idea to wait for a lock indefinitely?? Sorry if I sound frustrated, but I kinda am – I just paid for Supabase Pro and didn't expect this from a professional auth solution. I kinda spent an hour scratching my head figuring out what's wrong with my app. That said, I really appreciate the overall quality of Supabase and believe this is just an edge case to be fixed. I hope this investgation will be useful.

To Reproduce

This issue is not easily reproducible as it appears to be race condition or environment-dependent. However, it occurs in production on real devices where users experience complete authentication failure.

The fundamental issue is that the current implementation holds Web Locks indefinitely without a timeout, which violates basic concurrency principles. Any scenario that prevents proper lock cleanup can trigger this deadlock.

Expected behavior

Supabase Auth should be able to recover from a situation where the lock is not properly released. The lock mechanism should have a timeout and fallback to ensure the client doesn't hang indefinitely.

Currently, the there is no acquireTimeout (-1 means no timeout):

https://github.com/supabase/auth-js/blob/aadf02e63179746a06451f4247a370dfd05740ea/src/GoTrueClient.ts#L358-L362

Maybe it should be set to some sane value, like maybe 1 minute.

Screenshots

The app doesn't launch as Auth never finished initializing, and User sees a white page.
Image

System information

  • OS: Android
  • Browser: Chrome
  • Version of supabase-js: 2.71.1
  • Affected code: @supabase/auth-js GoTrueClient

Additional context

Current workaround

Until a proper lease is implemented, I am currently working around this issue by specifying a noOpLock when initializing Supabase. However I don’t know what might go wrong if we skip the locks.

const noOpLock = async (name: string, acquireTimeout: number, fn: () => Promise<any>) => {
  return await fn()
}

const supabase = createClient(url, key, {
  auth: { lock: noOpLock }
})

Debug session and debug log

Checking the locks in JS Console

await navigator.locks.query()

{
  held: [
    {clientId: '0ccb43ce-27c2-423e-8cbe-63a9c2da37b4', mode: 'exclusive', name: 'lock:sb-nmzhiwafofgwvqucnbds-auth-token'}
  ],
  pending: [
    {clientId: '0ccb43ce-27c2-423e-8cbe-63a9c2da37b4', mode: 'exclusive', name: 'lock:sb-nmzhiwafofgwvqucnbds-auth-token'},
    {clientId: 'e6ee664e-e2d9-4f1d-8a9a-0ab0b5e83ee6', mode: 'exclusive', name: 'lock:sb-nmzhiwafofgwvqucnbds-auth-token'},
    {clientId: 'e6ee664e-e2d9-4f1d-8a9a-0ab0b5e83ee6', mode: 'exclusive', name: 'lock:sb-nmzhiwafofgwvqucnbds-auth-token'},
    {clientId: '9d09c2ce-ac43-4783-b356-e988cae6bc26', mode: 'exclusive', name: 'lock:sb-nmzhiwafofgwvqucnbds-auth-token'}
  ]
}

Debug logs showing the hang:

GoTrueClient@0 (2.71.1) 2025-09-13T19:24:55.355Z #_acquireLock begin -1
GoTrueClient@0 (2.71.1) 2025-09-13T19:24:55.355Z #onAuthStateChange() registered callback with id a5571c4b-9f69-4111-b314-119f2e0ecb87
(hangs here - never proceeds to lock acquisition)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinghas workaroundIssue has a valid workaround.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions