Steps to reproduce
- Run any Flutter app in debug mode on Windows (
flutter run -d windows); the default flutter create app is enough.
- Whether the crash occurs depends on the monitor handle values the Windows session hands out: it reproduces when
MonitorFromWindow/EnumDisplayMonitors returns an HMONITOR whose 32-bit value has the high bit set (for example 0xE02E16A5). On an affected machine it crashes on every run during display enumeration; on other machines it never happens, which is why this bug looks sporadic across the ecosystem.
Expected results
The app runs. Display ids reported by the Windows embedder are stable values that fit the engine display API on every machine.
Actual results
The engine converts the HMONITOR to a display id with a raw cast:
display.display_id = reinterpret_cast<FlutterEngineDisplayId>(monitor);
(engine/src/flutter/shell/platform/windows/display_manager.cc, and the same pattern in FlutterWindow::GetDisplayId.)
On 64-bit Windows, USER and GDI handles are 32-bit values that the OS sign-extends to pointer size (documented in "Interprocess Communication Between 32-bit and 64-bit Applications"). A handle like 0xE02E16A5 therefore arrives as 0xFFFFFFFFE02E16A5. That value no longer fits in the signed 64-bit integer the display id is converted to on its way into Dart and trips the converter's range assertion in debug builds, aborting the app.
Masking the handle to its lower 32 bits produces a stable, unique id; the significant bits of these handles are the lower 32 bits, so two distinct monitors cannot collide.
Code sample
Code sample
// Unmodified `flutter create bug` app; any app triggers the assertion on an
// affected machine because the failure happens during engine display
// enumeration, before any application code is relevant.
import 'package:flutter/material.dart';
void main() {
runApp(const MaterialApp(home: Scaffold(body: Center(child: Text('bug')))));
}
Screenshots or Video
Screenshots / Video demonstration
Not applicable: debug-mode abort, no visual state.
Logs
Logs
[ERROR:flutter/shell/common/shell.cc(120)] assertion failed val <= 0x7fffffffffffffffLL
[ERROR:flutter/fml/backtrace.cc(108)] Caught signal SIGABRT during program execution.
Frame 0: 00000001430CF2CB tonic::DartConverter<unsigned long long,void>::ToDart
Frame 1: 0000000143102D2F tonic::DartConverter<std::vector<unsigned long long,std::allocator<unsigned long long> >,void>::ToDart
Frame 2: 00000001431113C3 tonic::ToDart<std::vector<unsigned long long,std::allocator<unsigned long long> > >
Frame 3: 000000014310C74B flutter::PlatformConfiguration::UpdateDisplays
Frame 4: 00000001431B7F53 flutter::RuntimeController::SetDisplays
Frame 5: 0000000142FBBD61 flutter::Engine::SetDisplays
Frame 6: 000000014300FB09 flutter::Shell::OnDisplayUpdates::<lambda_63>::operator()
Frame 7: 000000014300FAC3 std::invoke<`lambda at ..\..\flutter\shell\common\shell.cc:2449:37' &>
Frame 8: 000000014300F8D7 std::_Func_impl_no_alloc<`lambda at ..\..\flutter\shell\common\shell.cc:2449:37',void>::_Do_call
Frame 9: 00000001401F35A4 std::_Func_class<void>::operator()
Frame 10: 00000001409E4A7B fml::TaskRunner::RunNowOrPostTask
Frame 11: 0000000142FF34C1 flutter::Shell::OnDisplayUpdates
Frame 12: 000000014088351C FlutterEngineNotifyDisplayUpdate
Frame 13: 00000001406B47F7 flutter::FlutterWindowsEngine::UpdateDisplay
Frame 14: 000000014069207E flutter::DisplayManagerWin32::UpdateDisplays
Frame 15: 00000001406B26E3 flutter::FlutterWindowsEngine::Run
Frame 16: 00000001406B1302 flutter::FlutterWindowsEngine::Run
Captured on the affected machine described above. This particular capture is
from the engine's own test suite (FlutterWindowsEngineTest.RunHeadless in
flutter_windows_unittests), which boots a real engine and enumerates the
session's real monitors, so it hits the identical code path an app hits: the
crash is during display enumeration inside FlutterWindowsEngine::Run
(frames 0 through 16 are the same for any Flutter app on such a machine).
This also means the bug reproduces in-tree on an affected session by running
flutter_windows_unittests --gtest_filter=FlutterWindowsEngineTest.RunHeadless.
Flutter Doctor output
Doctor output
[√] Flutter (Channel stable, 3.44.4, on Microsoft Windows [Version 10.0.19045.6466], locale de-DE) [874ms]
• Flutter version 3.44.4 on channel stable at C:\Users\serha\flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision ad70ec4617 (3 weeks ago), 2026-06-24 11:07:06 -0700
• Engine revision 53bfd6d932
• Dart version 3.12.0 (build 3.12.0-139.0.dev)
• DevTools version 2.54.0
• Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios, cli-animations, enable-native-assets, enable-swift-package-manager, omit-legacy-version-file, enable-lldb-debugging, enable-uiscene-migration
[√] Windows Version (10 Pro 64-bit, 22H2, 2009) [5,4s]
[√] Android toolchain - develop for Android devices (Android SDK version 36.1.0) [15,9s]
• Android SDK at C:\Users\serha\AppData\Local\Android\sdk
• Emulator version 31.2.9.0 (build_id 8316981) (CL:N/A)
• Platform android-36, build-tools 36.1.0
• Java binary at: C:\Program Files\Android\Android Studio1\jbr\bin\java
This is the JDK bundled with the latest Android Studio installation on this machine.
To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
• Java version OpenJDK Runtime Environment (build 17.0.11+0--11852314)
• All Android licenses accepted.
[√] Chrome - develop for the web [294ms]
• Chrome at C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
[√] Visual Studio - develop Windows apps (Visual Studio Build Tools 2022 17.14.20) [292ms]
• Visual Studio at F:\VS_CPP_Tools
• Visual Studio Build Tools 2022 version 17.14.36705.20
• Windows 10 SDK version 10.0.26100.0
[√] Connected device (3 available) [281ms]
• Windows (desktop) • windows • windows-x64 • Microsoft Windows [Version 10.0.19045.6466]
• Chrome (web) • chrome • web-javascript • Google Chrome 150.0.7871.115
• Edge (web) • edge • web-javascript • Microsoft Edge 150.0.4078.65
[√] Network resources [752ms]
• All expected network resources are available.
• No issues found!
Also reproduces on current master (both conversion sites still use the raw cast).
Steps to reproduce
flutter run -d windows); the defaultflutter createapp is enough.MonitorFromWindow/EnumDisplayMonitorsreturns anHMONITORwhose 32-bit value has the high bit set (for example0xE02E16A5). On an affected machine it crashes on every run during display enumeration; on other machines it never happens, which is why this bug looks sporadic across the ecosystem.Expected results
The app runs. Display ids reported by the Windows embedder are stable values that fit the engine display API on every machine.
Actual results
The engine converts the
HMONITORto a display id with a raw cast:(engine/src/flutter/shell/platform/windows/display_manager.cc, and the same pattern in
FlutterWindow::GetDisplayId.)On 64-bit Windows, USER and GDI handles are 32-bit values that the OS sign-extends to pointer size (documented in "Interprocess Communication Between 32-bit and 64-bit Applications"). A handle like
0xE02E16A5therefore arrives as0xFFFFFFFFE02E16A5. That value no longer fits in the signed 64-bit integer the display id is converted to on its way into Dart and trips the converter's range assertion in debug builds, aborting the app.Masking the handle to its lower 32 bits produces a stable, unique id; the significant bits of these handles are the lower 32 bits, so two distinct monitors cannot collide.
Code sample
Code sample
Screenshots or Video
Screenshots / Video demonstration
Not applicable: debug-mode abort, no visual state.
Logs
Logs
Captured on the affected machine described above. This particular capture is
from the engine's own test suite (
FlutterWindowsEngineTest.RunHeadlessinflutter_windows_unittests), which boots a real engine and enumerates thesession's real monitors, so it hits the identical code path an app hits: the
crash is during display enumeration inside
FlutterWindowsEngine::Run(frames 0 through 16 are the same for any Flutter app on such a machine).
This also means the bug reproduces in-tree on an affected session by running
flutter_windows_unittests --gtest_filter=FlutterWindowsEngineTest.RunHeadless.Flutter Doctor output
Doctor output
Also reproduces on current master (both conversion sites still use the raw cast).