Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter catching all unhandled exceptions

I'm trying to catch all unhandled exceptions in a Flutter app so I can sent it to a crash reporter. There are instructions on how to do this in the Flutter docs. I followed those, and added two bits of code to my app to catch exceptions:

Catch Dart errors by wrapping runApp in runZoned:

runZoned<Future<void>>(   () async {     runApp(MyApp());   },   onError: (dynamic error, StackTrace stackTrace) {     print("=================== CAUGHT DART ERROR");     // Send report   }, ); 

Catch flutter errors by setting FlutterError.onError:

FlutterError.onError = (FlutterErrorDetails details) {   print("=================== CAUGHT FLUTTER ERROR");   // Send report }; 

However, when I test this at runtime by throwing an exception from a button:

throw Exception("Just testing"); 

The exception appears in the console:

════════ Exception Caught By gesture ═══════════════════════════════════════════════════════════════ The following _Exception was thrown while handling a gesture: Exception: Just testing When the exception was thrown, this was the stack:

... etc

But I see no sign of my print statements (CAUGHT DART ERROR or CAUGHT FLUTTER ERROR), and setting breakpoints on those lines never seems to hit, so I think my exception handling code isn't catching it. Am I missing something?

Here's a minimal reproducible example (click the button, which throws an exception, but it's not caught as expected):

import 'dart:async'; import 'package:flutter/material.dart';  void main() =>   runZoned<Future<void>>(     () async {       runApp(MyApp());     },     onError: (dynamic error, StackTrace stackTrace) {       print("=================== CAUGHT DART ERROR");       // Send report       // NEVER REACHES HERE - WHY?     },   );  class MyApp extends StatefulWidget {   // This widget is the root of your application.   @override   _MyAppState createState() => _MyAppState(); }  class _MyAppState extends State<MyApp> {    @override   void initState() {     super.initState();      // This captures errors reported by the FLUTTER framework.     FlutterError.onError = (FlutterErrorDetails details) {       print("=================== CAUGHT FLUTTER ERROR");       // Send report       // NEVER REACHES HERE - WHY?     };   }    @override   Widget build(BuildContext context) {     return MaterialApp(       home: Scaffold(         body: SafeArea(           child: RaisedButton(             child: Text("Throw exception"),             onPressed: () {               throw Exception("This is a test exception");             },           ),         ),       ),     );   } } 
like image 502
James Allen Avatar asked Sep 10 '19 23:09

James Allen


People also ask

How do you get the unhandled exception in Flutter?

In order to catch all the exceptions in a block of code you wrap the code in try block and use multiple on-catch instructions to handle some specific exceptions, then use catch to handle all other unexpected exceptions, and finally use finally to run the code that should be invoked after the code in try block and in ...

How do you catch future error Flutter?

That error is handled by catchError() . If myFunc() 's Future completes with an error, then() 's Future completes with that error. The error is also handled by catchError() . Regardless of whether the error originated within myFunc() or within then() , catchError() successfully handles it.

How do you handle errors in Flutter?

Errors that don't occur within Flutter's callbacks can't be caught by the framework, but you can handle them by setting up a Zone . All errors caught by Flutter are routed to the FlutterError. onError handler. By default, this calls FlutterError.


1 Answers

Okay I figured out what's going on. Had a look at some related Flutter issues:

flutter tool is too aggressive about catching exceptions

Make hot mode a little less aggressive about catching errors

Break on "unhandled" exceptions when a debugger is attached

It looks like when in debug mode, the flutter framework catches a lot of exceptions, prints to the console (and sometimes shows in the UI itself in red and yellow), but doesn't re-throw - so they are effectively swallowed and there's no way for your own code to catch them. But, when you deploy in release mode, this doesn't happen. So my minimal reproducible example does catch exceptions when built in release mode.

like image 159
James Allen Avatar answered Sep 16 '22 14:09

James Allen