Uncaught errors
Every throw, grouped and counted.
Identical errors collapse into one row with a repeat count, so a flood of the same null-check doesn't bury a rarer, nastier one. Sort and filter by type, time, or frequency; drill in for the full stack.
- Message, type, first/last seen
- Repeat count per distinct error
- Full stack trace on drill-down
- Sort / filter / search
Null check operator used on a null value
SocketException: Connection refused (port 443)
Bad state: Cannot add to a closed StreamController
RangeError (index): Invalid value: Not in 0..3
Main-thread stalls
The jank that becomes an ANR.
A watchdog times the gap between main-isolate heartbeats. Anything over your threshold is logged with its duration, when it happened, and the likely cause — the synchronous decode, the blocking write, the layout pass that locked the UI.
1.2sjsonDecode on main isolate (2.1 MB)14:30:11
980msSynchronous file write14:27:39
720msImage decode on UI thread14:21:55
540msLarge list rebuild14:18:20
410msCold cache query14:05:03
Drill-down
From a count to the exact frame.
Null check operator used on a null value
at ChatRoomController.dispose chat_room.dart:54
at _ChatScreenState.deactivate chat_screen.dart:71
at StatefulElement.unmount framework.dart:5204
at BuildOwner.finalizeTree framework.dart:2988
Real code
It wires the zones for you.
FlutterRadar.init(
stability: StabilityConfig(
captureErrors: true, // FlutterError + zone
stallThreshold: Duration(milliseconds: 250),
),
);
// No try/catch plumbing — Radar owns the error zone
// and the main-thread watchdog. It never rethrows
// into your app.