Is there an existing issue for this?
Which plugins are affected?
Core
Which platforms are affected?
Web
Description
FirebaseCoreWeb.app() catches any exception thrown while resolving the JS SDK's app instance and unconditionally casts it to JSError, with no is JSError guard first:
https://github.com/firebase/flutterfire/blob/main/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart#L423-L436
FirebaseAppPlatform app([String name = defaultFirebaseAppName]) {
firebase.App app;
try {
app = guardNotInitialized(() => firebase.app(name));
return _createFromJsApp(app);
} catch (e) {
if (_getJSErrorCode(e as JSError) == 'app/no-app') { // <-- explicit unchecked cast
throw noAppExists(name);
}
throw _catchJSError(e); // <-- e is passed positionally into `_catchJSError(JSError e)` — implicit cast
}
}
The same unguarded pattern also exists a few lines earlier, in the secondary-app branch (line 389).
guardNotInitialized, in the same file, can itself throw a plain Dart FirebaseException — not a JSError — whenever the underlying firebase.app(name) JS call fails with an error whose message contains "of undefined":
Never _handleException(Object exception, StackTrace stackTrace) {
if (exception.toString().contains('of undefined')) {
throw coreNotInitialized(); // FirebaseException, not JSError
}
Error.throwWithStackTrace(exception, stackTrace);
}
So when that specific condition is hit, app()'s own catch block receives a FirebaseException (from coreNotInitialized()), immediately force-casts it to JSError, and throws a brand-new, unrelated TypeError that completely masks the original, actionable "Firebase core not initialized" exception.
This is the same anti-pattern already reported and fixed in _flutterfire_internals's _testException via #18176 / PR #18177 ("propagates plain Dart errors from Futures (e.g. ArgumentError on web)") — but that fix didn't cover this instance in firebase_core_web.dart's own app() method, which still has the identical unguarded-cast shape as of both the latest published version (3.10.0) and the current main branch (checked directly, same line numbers: 389, 393, 430, 434).
Reproducing the issue
Reliably reproduced in production (Chrome, Flutter Web) on a real app: an authenticated action that resolves FirebaseAuth.instance (login, Google sign-in) hits this path and crashes every time with the masking TypeError instead of a usable error message. An isolated minimal repro outside our app wasn't built, but the mechanism above is confirmed by decoding our production main.dart.js build's minified stack trace against its own source map back to firebase_core_web.dart:434 (the throw _catchJSError(e); line), on two separate builds — one on firebase_core_web 3.9.1, one on 3.10.0 after upgrading specifically to test whether #18436's fix (the concurrent script-loading / WebKit temporal-dead-zone race) resolved it. It did not — the crash signature and decoded throw site are identical on both versions, consistent with this being a separate, still-present bug rather than the race #18436 already fixed.
Suspected trigger: some transient condition causes the underlying firebase.app(name) JS call to fail with an error whose message contains "of undefined" (per _handleException's own check), converting it to coreNotInitialized(). In our app this happens on a later call to resolve the app/auth instance, after an earlier, successful touch of FirebaseAuth.instance during startup already completed without error — so whatever the underlying race is, it isn't limited to the very first access.
Firebase Core version
4.13.0
Flutter Version
3.44.8 (stable channel, Dart 3.12.2)
Relevant Log Output
Uncaught Error: TypeError: Instance of 'minified:Ps': type 'minified:Ps' is not a subtype of type 'minified:eg'
at oi.bX0 [as a] (main.dart.js:4909:23)
at oi.bXj (main.dart.js:4881:10)
at aDT.hP (main.dart.js:76436:14)
at bne.$1 (main.dart.js:60116:44)
at pW.oT (main.dart.js:142805:22)
at KK.oT (main.dart.js:142809:28)
at KK.aef (main.dart.js:141769:9)
at KK.b1D (main.dart.js:141735:7)
at KK.vR (main.dart.js:141758:3)
at pW.Hu (main.dart.js:142194:3)
... (rethrown 3x further up through the app's own Riverpod provider-construction call chain)
Decoded against our own build's source map:
main.dart.js:4909:23 -> dart-sdk rti.dart:1503 (_generalAsCheckImplementation) <- the failing cast itself
main.dart.js:4881:10 -> dart-sdk rti.dart:1319 (_installSpecializedAsCheck)
main.dart.js:76436:14 -> firebase_core_web-3.10.0/lib/src/firebase_core_web.dart:434 (FirebaseCoreWeb.app)
main.dart.js:60116:44 -> firebase_core_platform_interface-8.1.0/.../platform_interface_firebase_app.dart:19 (FirebaseApp._)
(remaining frames are our own app's Riverpod provider-construction call chain, not FlutterFire-specific)
Flutter dependencies
firebase_core: 4.13.0
firebase_core_web: 3.10.0
firebase_core_platform_interface: 8.1.0
firebase_auth: 6.5.7
firebase_auth_web: 6.2.6
firebase_auth_platform_interface: 9.0.6
cloud_firestore: 6.8.0
cloud_firestore_web: 5.7.2
_flutterfire_internals: 1.3.76
Additional context and comments
Suggested fix, mirroring PR #18177's own resolution of the identical pattern in _flutterfire_internals:
} catch (e) {
if (e is! JSError) {
Error.throwWithStackTrace(e, StackTrace.current); // preserve the real error (e.g. coreNotInitialized())
}
if (_getJSErrorCode(e) == 'app/no-app') {
throw noAppExists(name);
}
throw _catchJSError(e);
}
(and the analogous change at the secondary-app branch around line 389).
Happy to open a PR with this change if a maintainer confirms the approach — filing the issue first since there's no fully isolated minimal repro for the underlying "of undefined" trigger, only the confirmed masking-bug mechanism downstream of it.
Is there an existing issue for this?
Which plugins are affected?
Core
Which platforms are affected?
Web
Description
FirebaseCoreWeb.app()catches any exception thrown while resolving the JS SDK's app instance and unconditionally casts it toJSError, with nois JSErrorguard first:https://github.com/firebase/flutterfire/blob/main/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart#L423-L436
The same unguarded pattern also exists a few lines earlier, in the secondary-app branch (line 389).
guardNotInitialized, in the same file, can itself throw a plain DartFirebaseException— not aJSError— whenever the underlyingfirebase.app(name)JS call fails with an error whose message contains "of undefined":So when that specific condition is hit,
app()'s own catch block receives aFirebaseException(fromcoreNotInitialized()), immediately force-casts it toJSError, and throws a brand-new, unrelatedTypeErrorthat completely masks the original, actionable "Firebase core not initialized" exception.This is the same anti-pattern already reported and fixed in
_flutterfire_internals's_testExceptionvia #18176 / PR #18177 ("propagates plain Dart errors from Futures (e.g.ArgumentErroron web)") — but that fix didn't cover this instance infirebase_core_web.dart's ownapp()method, which still has the identical unguarded-cast shape as of both the latest published version (3.10.0) and the currentmainbranch (checked directly, same line numbers: 389, 393, 430, 434).Reproducing the issue
Reliably reproduced in production (Chrome, Flutter Web) on a real app: an authenticated action that resolves
FirebaseAuth.instance(login, Google sign-in) hits this path and crashes every time with the maskingTypeErrorinstead of a usable error message. An isolated minimal repro outside our app wasn't built, but the mechanism above is confirmed by decoding our productionmain.dart.jsbuild's minified stack trace against its own source map back tofirebase_core_web.dart:434(thethrow _catchJSError(e);line), on two separate builds — one onfirebase_core_web3.9.1, one on 3.10.0 after upgrading specifically to test whether #18436's fix (the concurrent script-loading / WebKit temporal-dead-zone race) resolved it. It did not — the crash signature and decoded throw site are identical on both versions, consistent with this being a separate, still-present bug rather than the race #18436 already fixed.Suspected trigger: some transient condition causes the underlying
firebase.app(name)JS call to fail with an error whose message contains "of undefined" (per_handleException's own check), converting it tocoreNotInitialized(). In our app this happens on a later call to resolve the app/auth instance, after an earlier, successful touch ofFirebaseAuth.instanceduring startup already completed without error — so whatever the underlying race is, it isn't limited to the very first access.Firebase Core version
4.13.0
Flutter Version
3.44.8 (stable channel, Dart 3.12.2)
Relevant Log Output
Decoded against our own build's source map:
(remaining frames are our own app's Riverpod provider-construction call chain, not FlutterFire-specific)
Flutter dependencies
Additional context and comments
Suggested fix, mirroring PR #18177's own resolution of the identical pattern in
_flutterfire_internals:(and the analogous change at the secondary-app branch around line 389).
Happy to open a PR with this change if a maintainer confirms the approach — filing the issue first since there's no fully isolated minimal repro for the underlying "of undefined" trigger, only the confirmed masking-bug mechanism downstream of it.