Skip to content

[firebase_auth_web] Auth.onWaitInitState() hangs forever when the first onAuthStateChanged emits an error (e.g. IndexedDB _openDb failure), blocking Firebase.initializeApp and leaving a blank page #18703

Description

@dganzella

Is there an existing issue for this?

  • I have searched the existing issues.

Which plugins are affected?

Auth

Which platforms are affected?

Web

Description

Bug description

On Flutter web, Firebase.initializeApp() intermittently never completes, leaving the app on a permanently blank page. A manual browser reload recovers it. The browser console shows a Firebase JS SDK auth error originating in IndexedDBLocalPersistence._openDb, thrown during the initial user restoration:

Image

IndexedDB can be transiently unavailable at page load (a browser storage race, private-mode restrictions, or third‑party storage partitioning when the serving origin differs from authDomain). When that happens, the JS SDK's initialization promise rejects and the first onAuthStateChanged callback fires with an error instead of a user.

Root cause

firebase_auth_web waits for the first auth-state event during plugin registration, via Auth.onWaitInitState() in packages/firebase_auth/firebase_auth_web/lib/src/interop/auth.dart (unchanged on master as of this writing):

Future<void> onWaitInitState() async {
  final completer = Completer();
  final nextWrapper = (auth_interop.UserJsImpl? user) {
    _initUser = User.getInstance(user);
    completer.complete();
  };

  final errorWrapper = (JSAny e) => _changeController!.addError(e);

  final unsubscribe =
      jsObject.onAuthStateChanged(nextWrapper.toJS, errorWrapper.toJS);

  await completer.future;
  unsubscribe.callAsFunction();
}

On the error path there are two defects:

  1. The completer is never completed on error. errorWrapper routes the error to _changeController and never calls completer.complete()/completeError(), so await completer.future waits forever.

  2. _changeController is null at this point. During registerWith the onAuthStateChanged stream getter has not been accessed yet, so _changeController is null and _changeController!.addError(e) throws a null-check error inside the JS callback — the error is not surfaced to Dart at all.
    onWaitInitState() is awaited inside FirebaseAuthWeb.registerWith (firebase_auth_web.dart, await authDelegate.onWaitInitState();), which is awaited during Firebase.initializeApp(). Because the completer never completes, Firebase.initializeApp() never returns, runApp is never reached, and the page stays blank. A reload creates a fresh JS Auth instance that (outside the unavailability window) succeeds, which is why reloading "fixes" it.

Note: this is distinct from the graceful "persistence not supported" fallback. getAuthInstance passes the persistence hierarchy [indexedDBLocalPersistence, browserLocalPersistence, browserSessionPersistence], which handles unsupported stores, but a hard runtime _openDb rejection surfaces as an init error that onWaitInitState mishandles rather than falling through.

Reproducing the issue

Steps to reproduce

  1. Flutter web app that awaits Firebase.initializeApp() before runApp, using default (IndexedDB-backed) auth persistence.
  2. Force IndexedDB open to fail/reject at page load (e.g. run in a context where IndexedDB is momentarily unavailable, block site data, or stub indexedDB.open to reject). This mimics the intermittent real-world failure.
  3. Load the app.

Firebase Core version

4.15.0

Flutter Version

3.47.4 / Dart: 3.13+

Relevant Log Output

at IndexedDBLocalPersistence._openDb (indexed_db.ts:252:5)
at IndexedDBLocalPersistence._withRetries (indexed_db.ts:270:18)
at IndexedDBLocalPersistence._withPendingWrite (indexed_db.ts:403:14)
at IndexedDBLocalPersistence._set (indexed_db.ts:405:18)
at PersistenceUserManager.setCurrentUser (persistence_user_manager.ts:69:3)
at AuthImpl.directlySetCurrentUser (auth_impl.ts:797:18)
at AuthImpl.reloadAndSetCurrentUserOrClear (auth_impl.ts:398:3)
at async auth_impl.ts:191:12

Flutter dependencies

Expand Flutter dependencies snippet
Replace this line with the contents of your `flutter pub deps -- --style=compact`.

Additional context and comments

No response

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions