Skip to content

[firebase_core_web]: Concurrent dynamic import()s race in WebKit — "ReferenceError: Cannot access 'SDK_VERSION' before initialization" crashes Firebase.initializeApp on iOS #18436

Description

@aqrc

Is there an existing issue for this?

  • I have searched the existing issues.

Which plugins are affected?

Core

Which platforms are affected?

Web

Description

On Flutter web, Firebase.initializeApp() intermittently throws in WebKit-based
browsers (Safari, WKWebView, and all iOS browsers, since they all embed WebKit):

JSObject: ReferenceError: Cannot access 'SDK_VERSION' before initialization.

The exception propagates out of FirebaseCoreWeb.initializeApp
(guardNotInitialized(() => firebase.SDK_VERSION),
firebase_core_web.dart:263 in 3.5.0; still present in 3.9.0), so apps that
await Firebase.initializeApp() before runApp() never render — the user
gets a blank page.

In our production Sentry data this occurred 968 times for 941 distinct users
in ~2 months
, and the browser distribution is conclusive — 100% WebKit:

browser events
Mobile Safari UI/WKWebView 601
Mobile Safari 228
Google app (iOS) 72
Chrome Mobile iOS 39
Safari (desktop) 21
DuckDuckGo iOS / Edge iOS / other 7
Chrome desktop / Firefox / Android 0

Root cause analysis

FirebaseCoreWeb._initializeCore() injects one script per registered service
and awaits them in parallel:

await Future.wait(
  _services.values.map((service) {
    ...
    return injectSrcScript(
      'https://www.gstatic.com/firebasejs/$version/firebase-${service.name}.js',
      'firebase_${service.override ?? service.name}',
    );
  }),
);

Each injectSrcScript performs a dynamic import(). Every component bundle
(firebase-auth.js, firebase-app-check.js, firebase-messaging.js, …)
statically imports from firebase-app.js — e.g. firebase-auth.js@12.15.0
begins with:

import{_getProvider,...,SDK_VERSION as i}from".../12.15.0/firebase-app.js";

So with N plugins registered, N concurrent dynamic imports converge on the
shared firebase-app.js module. WebKit has a long-standing evaluation-order
defect in exactly this situation: under the race it can hand back a module
namespace whose top-level bindings are still in the temporal dead zone.
Reading firebase.SDK_VERSION immediately afterwards then throws the
ReferenceError above. (Per the ES modules spec this pattern must be safe —
the module map dedupes and dependencies complete evaluation before dependents —
and V8/SpiderMonkey handle it correctly, which matches the 0 non-WebKit events.
The same Safari-only TDZ error class is documented outside Firebase entirely,
e.g. shopware/shopware#17715 with Vite chunks sharing modules.)

Because it's a startup race, it reproduces probabilistically — mostly on slow
networks inside WKWebView — which is presumably why it's been hard to pin down.
Related earlier reports that look like the same underlying race: #13107, #11243.

Suggested fix

Any of these in _initializeCore() would eliminate the race for everyone:

  1. Inject the service scripts sequentially, firebase-app.js first
    (simplest; adds a few ms to first init on web only), or
  2. Load all registered services through a single module graph — one
    generated <script type="module"> that statically imports every service
    bundle and assigns the window.firebase_* vars (static imports in one
    graph are evaluated once, in topological order), or
  3. Keep parallel loading but import firebase-app.js first and only then
    fan out to the component bundles.

Workaround for affected users

Pre-load the SDK in web/index.html as one static module graph; when
window.firebase_core is already set, _initializeCore() skips its own
injection (and falls back to it if this script fails to load). The version must
match supportedFirebaseJsSdkVersion of your resolved firebase_core_web:

<script type="module">
  import * as core from "https://www.gstatic.com/firebasejs/12.9.0/firebase-app.js";
  import * as auth from "https://www.gstatic.com/firebasejs/12.9.0/firebase-auth.js";
  import * as app_check from "https://www.gstatic.com/firebasejs/12.9.0/firebase-app-check.js";
  import * as messaging from "https://www.gstatic.com/firebasejs/12.9.0/firebase-messaging.js";
  window.firebase_core = core;
  window.firebase_auth = auth;
  window.firebase_app_check = app_check;
  window.firebase_messaging = messaging;
</script>

Reproducing the issue

No deterministic reproduction (it's a module-loader race in WebKit). Conditions
that maximize the incidence, per our production data: iOS WKWebView (in-app
browser), slow/high-latency network, ≥3 Firebase web plugins registered
(core + auth + app-check + messaging in our case), cold cache. Throttling the
network in Safari with a multi-plugin Flutter web app and repeatedly reloading
reproduces it occasionally.

Firebase Core version

4.5.0

Flutter Version

3.38.5

Relevant Log Output

JSObject: ReferenceError: Cannot access 'SDK_VERSION' before initialization.
  at .pub-cache/hosted/pub.dev/firebase_core_web-3.5.0/lib/src/firebase_core_web.dart:263  (FirebaseCoreWeb.initializeApp)
  at .pub-cache/hosted/pub.dev/firebase_core_web-3.5.0/lib/src/firebase_core_web.dart:421  (guardNotInitialized)

Flutter dependencies

Expand Flutter dependencies snippet
Dart SDK 3.10.4
Flutter SDK 3.38.5
- _flutterfire_internals 1.3.67 [collection firebase_core firebase_core_platform_interface flutter meta]
- firebase_app_check 0.4.1+4 [firebase_app_check_platform_interface firebase_app_check_web firebase_core firebase_core_platform_interface flutter]
- firebase_app_check_platform_interface 0.2.1+4 [_flutterfire_internals firebase_core flutter meta plugin_platform_interface]
- firebase_app_check_web 0.2.2+2 [_flutterfire_internals firebase_app_check_platform_interface firebase_core firebase_core_web flutter flutter_web_plugins web]
- firebase_auth 6.1.4 [firebase_auth_platform_interface firebase_auth_web firebase_core firebase_core_platform_interface flutter meta]
- firebase_auth_platform_interface 8.1.6 [_flutterfire_internals collection firebase_core flutter http meta plugin_platform_interface]
- firebase_auth_web 6.1.2 [firebase_auth_platform_interface firebase_core firebase_core_web flutter flutter_web_plugins http_parser meta web]
- firebase_core 4.5.0 [firebase_core_platform_interface firebase_core_web flutter meta]
- firebase_core_platform_interface 6.0.2 [collection flutter flutter_test meta plugin_platform_interface]
- firebase_core_web 3.5.0 [firebase_core_platform_interface flutter flutter_web_plugins meta web]
- firebase_crashlytics 5.0.8 [firebase_core firebase_core_platform_interface firebase_crashlytics_platform_interface flutter stack_trace]
- firebase_crashlytics_platform_interface 3.8.18 [_flutterfire_internals collection firebase_core flutter meta plugin_platform_interface]
- firebase_messaging 16.1.1 [firebase_core firebase_core_platform_interface firebase_messaging_platform_interface firebase_messaging_web flutter meta]
- firebase_messaging_platform_interface 4.7.6 [_flutterfire_internals firebase_core flutter meta plugin_platform_interface]
- firebase_messaging_web 4.1.2 [_flutterfire_internals firebase_core firebase_core_web firebase_messaging_platform_interface flutter flutter_web_plugins meta web]

Additional context and comments

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs AttentionThis issue needs maintainer attention.platform: webIssues / PRs which are specifically for web.plugin: coretype: bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions