Repository navigation
Open
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work lista: pluginsSupport for writing, building, and running plugin packagesSupport for writing, building, and running plugin packagesc: proposalA detailed proposal for a change to FlutterA detailed proposal for a change to Flutterengineflutter/engine related. See also e: labels.flutter/engine related. See also e: labels.team-ecosystemOwned by Ecosystem teamOwned by Ecosystem teamtriaged-ecosystemTriaged by Ecosystem teamTriaged by Ecosystem team
Description
Internal: b/327780213
Use case
Consider an unhandled Exception being thrown in a Flutter app's main Dart isolate. Typically, this Exception is expected to be handled by one or more of these three mechanisms:
The following example app shows an exception that surprisingly isn't handled by any of the above mechanisms:
import 'dart:async';
import 'dart:isolate';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() async {
final binding = WidgetsFlutterBinding.ensureInitialized();
binding.platformDispatcher.onError = (error, stackTrace) {
// boom is not caught here.
print('blah platformDispatcher got error $error');
return true;
};
Isolate.current.addErrorListener(
RawReceivePort((dynamic pair) {
final errorAndStackTrace = (pair as List<Object>).cast<String>();
// boom is not caught here.
print('blah isolate $errorAndStackTrace');
}).sendPort,
);
await runZonedGuarded(() async {
runApp(Container(color: Colors.red));
// Create the two method channels used in this demo.
const ping = MethodChannel('ping');
const pong = MethodChannel('pong');
// Throw an exception when the platform calls the `pong` channel.
pong.setMethodCallHandler((call) async {
throw Exception('boom');
});
// Kick-off the `pong` call by calling the `ping` channel
await ping.invokeMethod('');
}, (error, st) {
// boom is not caught here.
print('blah runZoneGuarded $error, $st');
});Instead, the exception is forwarded to the platform for handling via the MethodChannel, example implementation for Android:
package com.google.android.flutter.samples.minimal;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.Result;
public class MainActivity extends FlutterActivity {
@Override
public void configureFlutterEngine(FlutterEngine flutterEngine) {
PluginRegistrant.registerWith(flutterEngine);
var ping = new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), "ping");
var pong = new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), "pong");
ping.setMethodCallHandler(
(call, result) -> {
result.success(null);
pong.invokeMethod(
/* method */ "boom",
/* arguments */ null,
// Without this, the "boom" error in Dart will be silently dropped.
/* callback */ new Result() {
@Override
public void success(Object result) {
android.util.Log.w("MinimalActivity", "blah success");
}
@Override
public void error(String errorCode, String errorMessage, Object errorDetails) {
android.util.Log.w(
"MinimalActivity",
"blah error errorCode="
+ errorCode
+ " errorMessage="
+ errorMessage
+ " errorDetails="
+ errorDetails);
}
@Override
public void notImplemented() {
android.util.Log.w("MinimalActivity", "blah notimplemented");
}
});
});
}
}Proposal
Instead of always forwarding exceptions thrown in Dart method call handlers back to the platform, provide an otpional mechanism for those exceptions to escape and be handled in Dart.
Reacted by ljmatan
Metadata
Metadata
Assignees
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work lista: pluginsSupport for writing, building, and running plugin packagesSupport for writing, building, and running plugin packagesc: proposalA detailed proposal for a change to FlutterA detailed proposal for a change to Flutterengineflutter/engine related. See also e: labels.flutter/engine related. See also e: labels.team-ecosystemOwned by Ecosystem teamOwned by Ecosystem teamtriaged-ecosystemTriaged by Ecosystem teamTriaged by Ecosystem team
Activity
stuartmorgan-g commentedon Mar 12, 2024
Based on our own experience in our plugins, having the exceptions stay on the Dart side is probably a better outcome for most of our use cases as well; this definitely seems like a reasonable proposal.