Skip to content

"Null check operator used on a null value" during hot reload #192227

Closed

Description

@goderbauer

I am running flutter run --machine -d web-server --web-port 3000 --web-hostname 0.0.0.0 and hot reloading with

[
  {
    "method": "app.restart",
    "id": 1,
    "params": {
      "appId": "e5a62088-0341-43ea-a18f-83aa691aab4f",
      "fullRestart": false
    }
  }
]

sometimes fails as follows:

  [{"event":"app.progress","params":{"appId":"e5a62088-0341-43ea-a18f-83aa691aab4f","id":"15","progressId":"hot.reload","message":"Performing hot reload...","finished":false}}]
  [{"event":"app.progress","params":{"appId":"e5a62088-0341-43ea-a18f-83aa691aab4f","id":"16","progressId":null,"message":"Waiting for connection from debug service on Web Server...","finished":false}}]
  Null check operator used on a null value
  [{"event":"app.progress","params":{"appId":"e5a62088-0341-43ea-a18f-83aa691aab4f","id":"16","progressId":null,"finished":true}}]
  [{"event":"app.progress","params":{"appId":"e5a62088-0341-43ea-a18f-83aa691aab4f","id":"15","progressId":"hot.reload","finished":true}}]
  [{"id":1,"result":{"code":1,"message":"Failed to recompile application."}}] 

I haven't been able to make much sense of it. The Null check operator used on a null value in there is curious. I have verified that the app under test does not have any nullability issues, so I suspect that something is crashing in the server during hot reload / recompilation.

I currently don't have a way to reproduce this reliably. I'll try to get more information on that... It's unfortunate that no stack trace is given...

Activity

  1. goderbauer commented on Sep 3, 2026

    @goderbauer
    MemberAuthor

    cc @bkonyi sorry that this is so vague... I'll try to obtain more details...

  2. added
    toolAffects the "flutter" command-line tool. See also t: labels.
    t: hot reloadReloading code during "flutter run"
    platform-webWeb applications specifically
    team-webOwned by Web platform team
    on Sep 3, 2026
  3. goderbauer commented on Sep 3, 2026

    @goderbauer
    MemberAuthor

    AI thinks that the "Null check operator used on a null value" exception is caught here and then forwarded without the stacktrace:

    https://github.com/dart-lang/sdk/blob/cbdda8b4e08d686a811672e8e7de67bacb4afb43/pkg/frontend_server/lib/frontend_server.dart#L1324

    As soon as I can I'll verify with https://dart-review.googlesource.com/c/sdk/+/545260 to see if I can get a stack trace out of it to verify and help with further debugging.

  4. flutter-zl commented on Sep 9, 2026

    @flutter-zl
    Contributor

    @goderbauer Do you ever hit the bug again and get the stacktrace?

  5. added
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Sep 9, 2026
  6. goderbauer commented on Sep 11, 2026

    @goderbauer
    MemberAuthor

    @flutter-zl I was able to capture the following stack trace:

    Null check operator used on a null value
    #0 FrontendCompiler.writeJavaScriptBundle (package:frontend_server/frontend_server.dart:1100)
    <asynchronous suspension>
    #1 FrontendCompiler.recompileDelta (package:frontend_server/frontend_server.dart:1312)
    <asynchronous suspension>
    #2 listenAndCompile.<anonymous closure> (package:frontend_server/frontend_server.dart:1806)
    <asynchronous suspension>
    

    With that, I can also confirm that https://dart-review.googlesource.com/c/sdk/+/545300 did not fix it :/ (FYI @bkonyi)

  7. removed
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Sep 11, 2026
  8. goderbauer commented on Sep 11, 2026

    @goderbauer
    MemberAuthor

    AI tracked this down and also assisted in writing this comment :)

    It's a different null check than the one 545300 fixed, which is why that CL didn't help.

    Root cause

    The ! is _generator.lastKnownGoodResult! in writeJavaScriptBundle. lastKnownGoodResult is only populated by IncrementalCompiler.accept(), so it is null until the client sends its first accept. But recompileDelta hardcodes fullComponent: false and therefore always takes the bundler.invalidate(...) branch, which dereferences it.

    So the frontend server implicitly requires compile → accept → recompile, and crashes on compile → recompile. Nothing in the protocol enforces that ordering. It only affects DDC — the VM path (writeDillFile) never touches lastKnownGoodResult.

    Why we hit it with --machine

    AppDomain.startApp sends the app.start event (with the appId) before runner.run() is called:

    https://github.com/flutter/flutter/blob/master/packages/flutter_tools/lib/src/commands/daemon.dart#L1025-L1068

    Meanwhile ResidentWebRunner.run() does the initial compile and only calls generator.accept() after _updateDevFS() has returned, i.e. after a fair amount of additional awaited work:

    https://github.com/flutter/flutter/blob/master/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart#L336-L343

    So a client that already has the appId can send app.restart in the window between "initial compile finished" and "accept sent". ResidentCompiler serializes the requests, so the recompile lands right after the compile but before the accept — and lastKnownGoodResult is still null. That explains why it's intermittent and why I couldn't reproduce it on demand.

    I suspect #152819 (same crash via the Debug Adapter, which is also --machine) is the same root cause.

    Fix

    Dart-side CL: https://dart-review.googlesource.com/c/sdk/+/548680

    When there is no accepted delta, the bundler is initialized from the full component instead of diffing. That's exact rather than a workaround: IncrementalCompiler.compile() returns _combinePendingDeltas(false), the union of all not-yet-accepted deltas, which is the same shape of component the initial compile passes to bundler.initialize.

    Reproduced deterministically in a test (compile, then recompile without accept): it fails with exactly Null check operator used on a null value before the fix and passes after.

    Still open on the flutter side

    The crash is gone, but the ordering is still wrong — an app.restart that races startup now silently causes a full bundle rebuild instead of a delta. Options:

    • don't service app.restart until the initial run() has completed, or
    • call generator.accept() in the same synchronous continuation that observes report.success, or
    • route initial startup through the same operationQueue as _queueAndDebounceReloadAction.

    @bkonyi @flutter-zl — worth fixing separately?

    I'll also make sure that in our environment that surfaced this crash we will not issue app.restart before app.started is received to avoid this race altogether.

  9. self-assigned this
    on Sep 11, 2026
  10. added
    P1High-priority issues at the top of the work list
    triaged-webTriaged by Web platform team
    on Sep 11, 2026
  11. reopened this on Sep 15, 2026
  12. added a commit that references this issue on Sep 15, 2026
    0a34be7
  13. github-actions commented on Sep 29, 2026

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  14. locked as resolved and limited conversation to collaborators on Sep 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

P1High-priority issues at the top of the work listplatform-webWeb applications specificallyt: hot reloadReloading code during "flutter run"team-webOwned by Web platform teamtoolAffects the "flutter" command-line tool. See also t: labels.triaged-webTriaged by Web platform team

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions