Repository navigation
After upgrading Flutter to 3.29.3 image.toByteData throws empty Exception #171946
Copy link
Copy link
Closed
Closed
Copy link
Labels
P1High-priority issues at the top of the work listHigh-priority issues at the top of the work listengineflutter/engine related. See also e: labels.flutter/engine related. See also e: labels.found in release: 3.35Found to occur in 3.35Found to occur in 3.35found in release: 3.36Found to occur in 3.36Found to occur in 3.36has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onr: fixedIssue is closed as already fixed in a newer versionIssue is closed as already fixed in a newer versionteam-engineOwned by Engine teamOwned by Engine teamtriaged-engineTriaged by Engine teamTriaged by Engine teamwaiting for PR to land (fixed)A fix is in flightA fix is in flight
Description
Steps to reproduce
- Open Flutter app with flutter version 3.29 on Android emulator
- Add code which calls method image.toByteData multiple times in cycle
- It is reproducable on emulators and real devices; The bug appears not constantly - for instance, if you will have 10 attempts, it will run 8 times without any errors and it will throw an exception twice
Part of Firebase Crashlytics log is below
Non-fatal Exception: io.flutter.plugins.firebase.crashlytics.FlutterError: Exception:
at _CustomZone.registerBinaryCallback(dart:async)
at _RouteMapState._initMarkers(route_map.dart:134)
at _RouteMapState.didUpdateWidget.<fn>(route_map.dart:75)
at SchedulerBinding._invokeFrameCallback(binding.dart:1438)
at SchedulerBinding.handleDrawFrame(binding.dart:1365)
at SchedulerBinding._handleDrawFrame(binding.dart:1204)
- It was not reproducable on Flutter 3.27.3 or lower
Expected results
Method image.toByteData doesn't throw any exception, code after it is performing
Actual results
Method image.toByteData throws exception without any desciption
Code sample
Code sample
Future<BitmapDescriptor?> method() async {
for (var index = 0; index < 3; index++) {
await _generateMarker(index);
}
}
Future<BitmapDescriptor?> _generateMarker(int index) async {
final markerSize = 28;
final iconSize = markerSize + (_strokeWidth * 2).round();
final centerMarker = iconSize / 2;
final radius = markerSize / 2;
final backgroundPaint = Paint()..isAntiAlias = true;
final pictureRecorder = ui.PictureRecorder();
final canvas = Canvas(pictureRecorder);
final textSpan = TextSpan(
text: index.toString(),
style: TextStyle(
fontSize: 14,
fontFamily: 'Inter',
fontWeight: FontWeight.normal,
height: 20 / 14,
letterSpacing: 0,
textBaseline: TextBaseline.alphabetic,
decoration: TextDecoration.none,
leadingDistribution: TextLeadingDistribution.even,
),
);
final textPainter =
TextPainter(
text: textSpan,
textDirection: TextDirection.ltr,
)..layout(
minWidth: 0,
maxWidth: iconSize.toDouble(),
);
backgroundPaint.color = Colors.green;
canvas.drawCircle(Offset(centerMarker, centerMarker), radius, backgroundPaint);
textPainter.paint(
canvas,
Offset(
(iconSize - textPainter.width) / 2,
(iconSize - textPainter.height) / 2,
),
);
final pic = pictureRecorder.endRecording();
final img = await pic.toImage(iconSize.toInt(), iconSize.toInt());
final byteData = await img.toByteData(format: ui.ImageByteFormat.png); //<-- Exception throws here
final buffer = byteData?.buffer.asUint8List();
if (buffer == null) return null;
return BitmapDescriptor.fromBytes(buffer);
}Screenshots or Video
Screenshots / Video demonstration
[Upload media here]
Logs
Logs
E/flutter (14843): [ERROR:flutter/lib/ui/painting/image_encoding_impeller.cc(195)] Failed to submit commands.
I/flutter (14843): [Reporter.error]:
I/flutter (14843): _Exception: Exception:
I/flutter (14843): dart:async _CustomZone.registerBinaryCallback
I/flutter (14843): package:cargomart/src/presentation/screens/order_route_details/widgets/route_map.dart 134 _RouteMapState._initMarkers
I/flutter (14843): package:cargomart/src/presentation/screens/order_route_details/widgets/route_map.dart 75 _RouteMapState.didUpdateWidget.<fn>
I/flutter (14843): package:flutter/src/scheduler/binding.dart 1442 SchedulerBinding._invokeFrameCallback
I/flutter (14843): package:flutter/src/scheduler/binding.dart 1369 SchedulerBinding.handleDrawFrame
I/flutter (14843): package:flutter/src/scheduler/binding.dart 1208 SchedulerBinding._handleDrawFrameFlutter Doctor output
Doctor output
[✓] Flutter (Channel stable, 3.32.5, on macOS 15.3 24D60 darwin-arm64 (Rosetta), locale ru-RU)
[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 16.4)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2023.1)
[✓] VS Code (version 1.83.1)
[✓] Connected device (3 available)
[✓] Network resources
• No issues found!Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
P1High-priority issues at the top of the work listHigh-priority issues at the top of the work listengineflutter/engine related. See also e: labels.flutter/engine related. See also e: labels.found in release: 3.35Found to occur in 3.35Found to occur in 3.35found in release: 3.36Found to occur in 3.36Found to occur in 3.36has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onr: fixedIssue is closed as already fixed in a newer versionIssue is closed as already fixed in a newer versionteam-engineOwned by Engine teamOwned by Engine teamtriaged-engineTriaged by Engine teamTriaged by Engine teamwaiting for PR to land (fixed)A fix is in flightA fix is in flight
Activity
darshankawar commentedon Jul 10, 2025
@lighthead9288 Please provide us minimal but complete runnable and reproducible code sample (ex: main.dart) that shows the reported behavior.
lighthead9288 commentedon Jul 11, 2025
flutter_create_markers_application.zip
Steps to reproduce:
flutter pub getThe program throws an _Exception at this string:
darshankawar commentedon Jul 14, 2025
Thanks for the repo @lighthead9288, I do see the error in the snackbar:
But looking at the repo again, I see that there are some external library / implementations being used. Is it possible to narrow down the issue with
google_maps_flutterand without external plugins ?github-actions commentedon Aug 4, 2025
Without additional information, we are unfortunately not sure how to resolve this issue. We are therefore reluctantly going to close this bug for now.
If you find this problem please file a new issue with the same description, what happens, logs and the output of 'flutter doctor -v'. All system setups can be slightly different so it's always better to open new issues and reference the related ones.
Thanks for your contribution.
github-actions commentedon Aug 18, 2025
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.jason-simmons commentedon Sep 6, 2025
Reproduced this using the attached app on an Android emulator running Impeller/GLES.
It reproduces more easily if I patch the app's
_generatePointMarkerto make repeated calls toImage.toByteDataduring the initial press of the "Open" button.The issue is caused by a race between the raster thread merger and the Impeller image encoder. The sequence is:
EncodeImageAndInvokeDataCallbackEncodeImageAndInvokeDataCallbackqueues a task to the raster thread that will rasterize the image using Impeller.RasterThreadMerger::MergeWithLeaseMergeWithLeasemerges the raster thread into the platform thread. Any pending raster tasks will be executed on the platform thread.EncodeImageAndInvokeDataCallbackexecutes on the platform thread.ReactorGLES::Reactwill fail theCanReactOnCurrentThreadcheck.ImageEncodingImpeller::ConvertDlImageToSkImagewill log theFailed to submit commandserror, and the app'sImage.toByteDatacall will throw an exception.The issue does not always happen because another raster task (such as an
AcquireFrame) may run after theMergeWithLeaseand before theImageEncodingImpellertask. If that task makes an EGL context current on the platform thread, then when theImageEncodingImpellertask runs it will be able to execute GLES commands.Not sure what would be the best way to resolve this. It looks like the raster thread merger does not have a way to immediately make an EGL context current on the the merged thread.
So instead
ImageEncodingImpellermay need to use theSnapshotController::Delegateto activate an EGL context (similar to how the Skia image encoder implementation does this throughSnapshotControllerSkia::ConvertToRasterImage)@chinmaygarde
6 remaining items
Ensure that the raster thread has an EGL context before submitting th…
Ensure that the raster thread has an EGL context before submitting th…
Ensure that the raster thread has an EGL context before submitting th…
Ensure that the raster thread has an EGL context before submitting th…
github-actions commentedon Oct 2, 2025
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.Ensure that the raster thread has an EGL context before submitting th…
Ensure that the raster thread has an EGL context before submitting th…
Ensure that the raster thread has an EGL context before submitting th…