Skip to content

Craft better error message for OffsetLayer.toImage in the HTML renderer #49857

@domesticmouse

Description

@domesticmouse

I'm attempting to convert a Canvas widget's content to an image, using the following code. It works fine on iOS and macOS, but dies on the web.

  Future<void> _capturePng() async {
    RenderRepaintBoundary boundary =
        globalKey.currentContext.findRenderObject();
    ui.Image image = await boundary.toImage(pixelRatio: 1);
    ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
    Uint8List pngBytes = byteData.buffer.asUint8List();
    print('PNG Image size: ${pngBytes.length}');
  }

VSCode console output:


════════ Exception caught by scheduler library ═════════════════════════════════
The following assertion was thrown during a scheduler callback:
Assertion failed: org-dartlang-sdk:///flutter_web_sdk/lib/_engine/engine/surface/scene_builder.dart:267:12
retainedSurface.isActive || retainedSurface.isReleased
is not true

When the exception was thrown, this was the stack
throw_ (package:dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart:196:49)
assertFailed (package:dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart:26:3)
addRetained (package:build_web_compilers/lib/_engine/engine/surface/scene_builder.dart:267:55)
[_addToSceneWithRetainedRendering]
package:flutter/…/rendering/layer.dart:439
addChildrenToScene
package:flutter/…/rendering/layer.dart:1065
...
════════════════════════════════════════════════════════════════════════════════

JS Console stacktrace

errors.dart:147 Uncaught (in promise) Error: Exception: Incorrect sequence of push/pop operations while building scene surfaces. After building the scene the persisted surface stack must contain a single element which corresponds to the scene itself (_PersistedScene). All other surfaces should have been popped off the stack. Found the following surfaces in the stack:
PersistedScene, PersistedTransform
    at Object.throw_ [as throw] (errors.dart:196)
    at scene_builder.dart:24
    at _engine.SurfaceSceneBuilder.new.get [_persistedScene] (scene_builder.dart:31)
    at _engine.SurfaceSceneBuilder.new.build (scene_builder.dart:514)
    at layer$.OffsetLayer.new.buildScene (layer.dart:807)
    at layer$.OffsetLayer.new.toImage (layer.dart:1240)
    at toImage.next (<anonymous>)
    at runBody (async_patch.dart:86)
    at Object._async [as async] (async_patch.dart:125)
    at layer$.OffsetLayer.new.toImage (layer.dart:1229)
    at proxy_box.RenderRepaintBoundary.new.toImage (proxy_box.dart:2962)
    at main._MyHomePageState.new._capturePng (main.dart:35)
    at _capturePng.next (<anonymous>)
    at runBody (async_patch.dart:86)
    at Object._async [as async] (async_patch.dart:125)
    at main._MyHomePageState.new.[_capturePng] (main.dart:32)
    at _InkResponseState.new.[_handleTap] (ink_well.dart:705)
    at ink_well.dart:788
    at tap.TapGestureRecognizer.new.invokeCallback (recognizer.dart:182)
    at tap.TapGestureRecognizer.new.handleTapUp (tap.dart:486)
    at tap.TapGestureRecognizer.new.[_checkUp] (tap.dart:264)
    at tap.TapGestureRecognizer.new.handlePrimaryPointer (tap.dart:199)
    at tap.TapGestureRecognizer.new.handleEvent (recognizer.dart:470)
    at pointer_router.PointerRouter.new.[_dispatch] (pointer_router.dart:76)
    at pointer_router.dart:117
    at LinkedMap.new.forEach (linked_hash_map.dart:23)
    at pointer_router.PointerRouter.new.[_dispatchEventToRoutes] (pointer_router.dart:115)
    at pointer_router.PointerRouter.new.route (pointer_router.dart:101)
    at binding$5.WidgetsFlutterBinding.new.handleEvent (binding.dart:218)
    at binding$5.WidgetsFlutterBinding.new.dispatchEvent (binding.dart:198)
    at binding$5.WidgetsFlutterBinding.new.[_handlePointerEvent] (binding.dart:156)
    at binding$5.WidgetsFlutterBinding.new.[_flushPointerEventQueue] (binding.dart:102)
    at binding$5.WidgetsFlutterBinding.new.[_handlePointerDataPacket] (binding.dart:86)
    at _engine.PointerBinding.__.[_onPointerData] (pointer_binding.dart:129)
    at pointer_binding.dart:465
    at pointer_binding.dart:430
    at HTMLElement.<anonymous> (pointer_binding.dart:195)

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Issues that are less important to the Flutter projecta: error messageError messages from the Flutter frameworke: web_htmlHTML rendering backend for Webengineflutter/engine related. See also e: labels.found in release: 3.19Found to occur in 3.19found in release: 3.20Found to occur in 3.20good first issueRelatively approachable for first-time contributorshas reproducible stepsThe issue has been confirmed reproducible and is ready to work onplatform-webWeb applications specificallyr: solvedIssue is closed as solvedteam-webOwned by Web platform teamtriaged-webTriaged by Web platform team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions