Skip to content

Flutter runtime errorFlutter: “Binding has not yet been initialized” / “ServicesBinding.defaultBinaryMessenger was accessed before the binding was initialized”

The app crashes before the first frame with Binding has not yet been initialized (older Flutter versions say ServicesBinding.defaultBinaryMessenger was accessed before the binding was initialized). Code in main() called a plugin, such as Firebase, SharedPreferences or SystemChrome, before runApp. Plugins talk to the platform through the binding, and runApp is what normally creates it.

Short answer

Make main async and call WidgetsFlutterBinding.ensureInitialized() as its first line, before any await or plugin call. In tests, call TestWidgetsFlutterBinding.ensureInitialized(). In a background isolate, pass a RootIsolateToken and call BackgroundIsolateBinaryMessenger.ensureInitialized(token) first.

Why the binding isn’t ready, and the fix

  1. 01

    A plugin call in main() before runApp

    “You only need to call this method if you need the binding to be initialized before calling runApp.” Flutter, WidgetsFlutterBinding.ensureInitialized

    Firebase.initializeApp, SharedPreferences.getInstance, path_provider and SystemChrome.setPreferredOrientations all need the binding. Create it first.

    Future<void> main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await Firebase.initializeApp(
        options: DefaultFirebaseOptions.currentPlatform,
      );
      final prefs = await SharedPreferences.getInstance();
      runApp(MyApp(prefs: prefs));
    }
  2. 02

    A unit test that touches a plugin

    Plain test() blocks don’t create a binding; testWidgets does. Create the test binding at the top of main, and mock the plugin (for example SharedPreferences.setMockInitialValues) since there is no platform side in tests.

    void main() {
      TestWidgetsFlutterBinding.ensureInitialized();
      test('loads settings', () async {
        SharedPreferences.setMockInitialValues({});
        // ...
      });
    }
  3. 03

    A plugin call in a background isolate

    “A BinaryMessenger for use on background (non-root) isolates.” Flutter, BackgroundIsolateBinaryMessenger

    Isolate.run or compute starts a new isolate with no binding. Pass the root isolate token in and set up the background messenger before any plugin call. Not every plugin works off the main isolate.

    final token = RootIsolateToken.instance!;
    await Isolate.run(() async {
      BackgroundIsolateBinaryMessenger.ensureInitialized(token);
      final dir = await getApplicationDocumentsDirectory();
      // ...
    });

Checked against the vendor’s docs on : Flutter API: WidgetsFlutterBinding.ensureInitialized; Flutter API: BackgroundIsolateBinaryMessenger.

Rather hand it over?

Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.

Related: Flutter MissingPluginException · Flutter “Null check operator used on a null value” · Flutter LateInitializationError · Flutter “type 'Null' is not a subtype of type 'String'”

Questions

More on this error

Is it safe to call ensureInitialized every time?

Yes. It returns the existing binding if there is one, so calling it at the top of main costs nothing even when nothing needs it yet.

I added it and the app shows a white screen at start. Why?

Something awaited in main is slow or never finishes, such as a network call. Keep main to setup that must finish first, and load the rest after the first frame with a loading screen.

Can you fix it for me?

If one bug is the whole problem, the App Fix Ticket covers it: a written diagnosis first, then the fix. If the app has more going on, the Launch Check is a written check of the whole app. Each issue found is rated critical, high, medium or low, with where it is and how it was confirmed. No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.

A different error?

Describe it and get a written quote

Send the error and what you were doing. You get a written scope, a fixed price and a timeline; Simon replies by email, usually within one business day.