Skip to content

Flutter and Dart errorFlutter: “Null check operator used on a null value”

The app shows a red error screen in debug, or a grey box in release, and the log says Null check operator used on a null value. Somewhere the code put a ! after a value to promise Dart it is never null, and at runtime it was null. The stack trace points at the line; the fix is to handle the null case there instead of forcing it.

Short answer

Open the first line of the stack trace that is in your own code and find the ! on it. Replace it with a null check, a default (value ?? fallback), or the ?. operator. The usual culprits are snapshot.data! before a FutureBuilder has data, ModalRoute.of(context)!.settings.arguments on a route opened without arguments, a GlobalKey’s currentState! before its widget is on screen, map['key']! for a key the API did not send, and a field that is set later than the code that reads it.

Where the null comes from, and the fix

  1. 01

    A ! on a value that can still be null

    “A postfix exclamation mark (!) takes the expression on the left and casts it to its underlying non-nullable type.” Dart, Understanding null safety

    The ! operator turns a nullable value into a non-nullable one with no check, so the program stops if the value is null. Replace it with code that handles null: an if check, a default with ??, or ?. to skip the call.

    // crashes when name is null
    Text(user.name!)
    
    // handles it
    Text(user.name ?? 'Guest')
  2. 02

    snapshot.data! before the data arrives

    “If this is non-null, hasData will be true. If error is not null, this will be null.” Flutter, AsyncSnapshot.data

    A FutureBuilder or StreamBuilder builds before the future finishes, and on error. Reading snapshot.data! on that first build throws. Check hasError and hasData first, and show a loader until there is data. After an await in a State method, check mounted before using context or calling setState, because the widget may be gone.

    FutureBuilder<User>(
      future: _userFuture, // created in initState
      builder: (context, snapshot) {
        if (snapshot.hasError) return Text('${snapshot.error}');
        if (!snapshot.hasData) return const CircularProgressIndicator();
        return Text(snapshot.data!.name);
      },
    )
  3. 03

    currentState! on a GlobalKey

    “The current state is null if (1) there is no widget in the tree that matches this global key” Flutter, GlobalKey.currentState

    _formKey.currentState!.validate() throws if the Form with that key is not on screen yet, has been removed, or the key is attached to a different widget. Make sure the key is passed to the widget you read it from, and call it from a button press or after the first frame, not in initState.

  4. 04

    A map key or JSON field that was not sent

    “The index [] operator on the Map class returns null if the key isn't present.” Dart, Understanding null safety

    json['avatar']! works until the API leaves the field out or sends null. Treat API fields as optional unless the API guarantees them, and give the model a default or a nullable type.

    final avatar = json['avatar'] as String?; // may be null
    final count = (json['count'] as int?) ?? 0;

Checked against the vendor’s docs on : Dart: Understanding null safety (the ! operator, Map lookups); Flutter API: AsyncSnapshot.data; Flutter API: GlobalKey.currentState.

Rather hand it over?

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

Related: Flutter “setState() called during build” · Flutter “A RenderFlex overflowed” · Firebase “No Firebase App [DEFAULT]” · Flutter requires a newer Kotlin Gradle plugin

Questions

More on this error

Why does it only crash for some users?

The null depends on data or timing: a field some accounts do not have, a slow network that leaves a FutureBuilder without data on the first build, or a screen opened before a value was loaded. Search the code for ! on values that come from the network or from storage.

Should I remove every ! from the code?

No. A ! right after a check that proves the value is not null is fine. Remove the ones on values that come from outside the code (API data, storage, keys, async results), where null is a real possibility.

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.