Pillar 03 · Stability

See the freeze before your users do.

Uncaught errors get captured with the count of how often each one repeats and the stack that threw it. A main-thread watchdog catches the stalls — the ANR-like freezes a crash report never even names.

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
Uncaught errors 4 distinct · 41 total sort: count
Null check operator used on a null value
_TypeError14:31:08×23
SocketException: Connection refused (port 443)
SocketException14:19:02×8
Bad state: Cannot add to a closed StreamController
StateError14:22:41×6
RangeError (index): Invalid value: Not in 0..3
RangeError14:28:55×4

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.

configurable threshold sortable by duration
Main-thread stalls 5 over 250ms
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
_TypeError last 14:31:08 ×23
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.

main.dart
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.