-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Description
Is there an existing issue for this?
- I have searched the existing issues.
Which plugins are affected?
Core
Which platforms are affected?
Web
Description
The Firebase.apps getter in firebase_core_web throws an uncaught JavaScriptError when running in WASM mode (--wasm flag), even though the code has a try-catch block to handle this case.
Reproducing the issue
- Create a Flutter web app with Firebase
- Access
Firebase.appsbefore callingFirebase.initializeApp() - Build/run with
flutter run -d chrome --release --wasm
import 'package:firebase_core/firebase_core.dart';
void main() async {
// This line throws JavaScriptError in WASM mode
// but returns [] in non-WASM web mode
print('Apps before init: ${Firebase.apps}');
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
}Expected Behavior
Firebase.apps should return an empty list (as it does in non-WASM web builds).
Actual Behavior
Throws JavaScriptError at firebase_core_web.dart:230.
Firebase Core version
firebase_core: 4.3.0 / firebase_core_web: 3.3.1
Flutter Version
3.38.5
Relevant Log Output
JavaScriptError
at module0.FirebaseCoreWeb.apps (firebase_core_web.dart:230:5)
at module0.Firebase.apps (firebase.dart:28:22)
at module0.Firebase.initializeApp (firebase.dart:19:32)
at module0._awaitHelper closure at org-dartlang-sdk:///dart-sdk/lib/_internal/wasm/lib/async_patch.dart:104:5 (async_patch.dart:105:32)
Uncaught Exception: WebAssembly.ExceptionFlutter dependencies
Expand Flutter dependencies snippet
# Relevant dependencies for the issue:
Dart SDK 3.10.4
Flutter SDK 3.38.5
firebase_core: 4.3.0
- firebase_core_platform_interface 5.4.0
- firebase_core_web 3.3.1
firebase_auth: 6.1.3
- firebase_auth_platform_interface 7.5.1
- firebase_auth_web 6.1.1
firebase_app_check: 0.4.1+3
- firebase_app_check_platform_interface 0.1.2+3
- firebase_app_check_web 0.2.2+1
firebase_analytics: 12.1.0
- firebase_analytics_platform_interface 5.1.1
- firebase_analytics_web 0.6.1+1
firebase_remote_config: 6.1.3
- firebase_remote_config_platform_interface 2.1.1
- firebase_remote_config_web 1.10.2Additional context and comments
Related Issues
- This is a regression of 🐛 [firebase_core] Firebase.apps throws exception in web if none is initialised #9726 specifically for WASM builds
Analysis
The apps getter in firebase_core_web.dart relies on exception handling to detect when Firebase is not initialized:
List<FirebaseAppPlatform> get apps {
try {
return firebase.apps.map(_createFromJsApp).toList(growable: false);
} catch (exception) {
if (exception.toString().contains('of undefined')) {
return [];
} else {
rethrow;
}
}
}This works in JS (non-WASM) web builds, but fails in WASM mode. While related Dart SDK issues around WASM exception handling have been fixed (dart-lang/sdk#55457, dart-lang/sdk#56949), there may still be edge cases or inconsistencies in how JavaScript exceptions are caught in dart2wasm (see dart-lang/sdk#55496 for ongoing discussion about JS interop error handling).
Proposed Fix
Instead of relying on exception handling, proactively check if the Firebase core module is loaded before accessing firebase.apps. This pattern is already used elsewhere in the same file (line 204 in _initializeCore()):
List<FirebaseAppPlatform> get apps {
// Check if Firebase core module is loaded before accessing firebase.apps.
// This avoids triggering a JS exception when Firebase is not initialized,
// which is more efficient than relying on exception handling.
if (globalContext.getProperty('firebase_core'.toJS) == null) {
return [];
}
try {
return firebase.apps.map(_createFromJsApp).toList(growable: false);
} catch (exception, stackTrace) {
// ... existing fallback handling
}
}This approach:
- Avoids triggering an exception for an expected case (more efficient)
- Uses a proven pattern already in the codebase
- Works reliably in both JS and WASM modes
Workaround
Wrap Firebase.apps access in application code with an additional try-catch:
List<FirebaseApp> _getExistingApps() {
try {
return Firebase.apps;
} catch (_) {
return [];
}
}