Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Image disposes its image too early, causing errors such as "Cannot clone a disposed image" #110129

Closed
fzyzcjy opened this issue Aug 24, 2022 · 3 comments · Fixed by #110131
Closed
Labels
a: images Loading, displaying, rendering images c: crash Stack traces logged to the console found in release: 3.0 Found to occur in 3.0 found in release: 3.1 Found to occur in 3.1 framework flutter/packages/flutter repository. See also f: labels. has reproducible steps The issue has been confirmed reproducible and is ready to work on r: fixed Issue is closed as already fixed in a newer version

Comments

@fzyzcjy
Copy link
Contributor

fzyzcjy commented Aug 24, 2022

Bug analysis and solution

Summary: Looking at Image. When its new image is decoded, it will immediately dispose its old image handle. However, this is logically wrong - the old image handle may still be used in the (near) future.

At the first glance, this looks impossible, because when the old image handle is disposed, we will no longer give it to child widget tree. And we all know that, Flutter builds widget tree from ancestors to descendants. Therefore, as long as the ancestor (Image) provides the new image handle to its children (RawImage), its children should not use the old image handle after it is disposed.

However, it is not true and this bug is indeed there. There are some special but very widely used widgets that "breaks" this mental modal, such as the LayoutBuilder. When we have something like WidgetOne(child: LayoutBuilder(builder: WidgetTwo())), and WidgetOne and WidgetTwo both markNeedsBuild (such as by setState), then the build order is indeed: WidgetOne - WidgetTwo(with old data) - LayoutBuilder - WidgetTwo(with new data). The "WidgetTwo(with old data)" will cause bugs in our case. In our case, the "old data" is equivalent to "the image handle that we have disposed", so we are indeed using a disposed image handle.

Reproducible samples are given below to verify the theoretical analysis.


Steps to Reproduce

Run the following self-contained test. (I added a lot of logs so you can see what is happening)

Expected results:
No error

Actual results:
Errors. Please have a look at logs below.

Code sample
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  const imageData =
      'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=';

  testWidgets('hi', (tester) async {
    final outerListenable = ValueNotifier<int>(0);
    final innerListenable = ValueNotifier<int>(0);

    var frameBuilderCountWithImage = 0;
    var image = MemoryImage(base64Decode(imageData));

    Future<void> runAsyncAndIdle() async {
      for (var i = 0; i < 20; ++i) {
        await tester.runAsync(() => Future<void>.delayed(Duration.zero));
        await tester.idle();
      }
    }

    await tester.pumpWidget(MaterialApp(
      home: Center(
        child: ValueListenableBuilder<void>(
          valueListenable: outerListenable,
          builder: (_, __, ___) {
            debugPrint('build outer-Observer');
            return Image(
              image: image,
              frameBuilder: (_, child, __, ___) {
                final peekChildImage = ((child as Semantics).child! as RawImage).image;
                debugPrint('build Image.frameBuilder peekChildImage=$peekChildImage');

                if (peekChildImage != null) {
                  frameBuilderCountWithImage++;
                }

                return LayoutBuilder(builder: (_, __) {
                  debugPrint('build LayoutBuilder peekChildImage=$peekChildImage');

                  return ValueListenableBuilder(
                    valueListenable: innerListenable,
                    builder: (_, __, ___) {
                      debugPrint('build inner-Observer peekChildImage=$peekChildImage');

                      return KeyedSubtree(
                        key: UniqueKey(),
                        child: child,
                      );
                    },
                  );
                });
              },
            );
          },
        ),
      ),
    ));

    while (frameBuilderCountWithImage == 0) {
      debugPrint('pump to wait for frameBuilderCountWithImage');
      await runAsyncAndIdle();
      await tester.pump();
    }

    debugPrint('--- modify observable ---');
    image = MemoryImage(base64Decode(imageData)); // imagine it is a new image
    outerListenable.value++;
    innerListenable.value++;

    debugPrint('--- pump ---');
    frameBuilderCountWithImage = 0;
    while (frameBuilderCountWithImage == 0) {
      debugPrint('pump to wait for frameBuilderCountWithImage');
      await runAsyncAndIdle();
      innerListenable.value++;
      await tester.pump();
    }
  });
}
Logs
/Users/tom/fvm/default/bin/flutter --no-color test --machine --start-paused test/hello.dart
Testing started at 08:53 ...

build outer-Observer
build Image.frameBuilder peekChildImage=null
build LayoutBuilder peekChildImage=null
build inner-Observer peekChildImage=null
hi RawImage#70162 createRenderObject image=Null#007db
pump to wait for frameBuilderCountWithImage
build Image.frameBuilder peekChildImage=[1×1]
build LayoutBuilder peekChildImage=[1×1]
build inner-Observer peekChildImage=[1×1]
hi RawImage#1016a createRenderObject image=Image#da4a8
--- modify observable ---
--- pump ---
pump to wait for frameBuilderCountWithImage
build outer-Observer
build Image.frameBuilder peekChildImage=null
build inner-Observer peekChildImage=[1×1]
hi RawImage#1016a createRenderObject image=Image#da4a8
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following StateError was thrown building KeyedSubtree-[#358f6]:
Bad state: Cannot clone a disposed image.
The clone() method of a previously-disposed Image was called. Once an Image object has been
disposed, it can no longer be used to create handles, as the underlying data may have been released.

The relevant error-causing widget was:
  KeyedSubtree-[#358f6]
  KeyedSubtree:file:///Users/tom/Main/yplusplus/frontend/yplusplus_core/test/hello.dart:48:30

When the exception was thrown, this was the stack:
#0      Image.clone (dart:ui/painting.dart:1815:7)
#1      RawImage.createRenderObject (package:flutter/src/widgets/basic.dart:5794:21)
#2      RenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5662:52)
...     Normal element mounting (10 frames)
#12     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3817:16)
#13     Element.updateChild (package:flutter/src/widgets/framework.dart:3545:20)
#14     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#15     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4977:11)
#16     Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#17     BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2659:19)
#18     AutomatedTestWidgetsFlutterBinding.drawFrame (package:flutter_test/src/binding.dart:1183:19)
#19     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:370:5)
#20     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1146:15)
#21     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1083:9)
#22     AutomatedTestWidgetsFlutterBinding.pump.<anonymous closure> (package:flutter_test/src/binding.dart:1050:9)
#25     TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:71:41)
#26     AutomatedTestWidgetsFlutterBinding.pump (package:flutter_test/src/binding.dart:1037:27)
#27     WidgetTester.pump.<anonymous closure> (package:flutter_test/src/widget_tester.dart:608:53)
#30     TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:71:41)
#31     WidgetTester.pump (package:flutter_test/src/widget_tester.dart:608:27)
#32     main.<anonymous closure> (file:///Users/tom/Main/yplusplus/frontend/yplusplus_core/test/hello.dart:79:20)
<asynchronous suspension>
<asynchronous suspension>
(elided 5 frames from dart:async and package:stack_trace)

════════════════════════════════════════════════════════════════════════════════════════════════════
build LayoutBuilder peekChildImage=null
build inner-Observer peekChildImage=null
hi RawImage#6170d createRenderObject image=Null#007db
pump to wait for frameBuilderCountWithImage
build Image.frameBuilder peekChildImage=[1×1]
build inner-Observer peekChildImage=null
hi RawImage#6170d createRenderObject image=Null#007db
build LayoutBuilder peekChildImage=[1×1]
build inner-Observer peekChildImage=[1×1]
hi RawImage#e64b1 createRenderObject image=Image#e025c
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following StateError was thrown building KeyedSubtree-[#358f6]:
Bad state: Cannot clone a disposed image.
The clone() method of a previously-disposed Image was called. Once an Image object has been
disposed, it can no longer be used to create handles, as the underlying data may have been released.

When the exception was thrown, this was the stack:
#0      Image.clone (dart:ui/painting.dart:1815:7)
#1      RawImage.createRenderObject (package:flutter/src/widgets/basic.dart:5794:21)
#2      RenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5662:52)
...     Normal element mounting (10 frames)
#12     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3817:16)
#13     Element.updateChild (package:flutter/src/widgets/framework.dart:3545:20)
#14     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#15     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4977:11)
#16     Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#17     BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2659:19)
#18     AutomatedTestWidgetsFlutterBinding.drawFrame (package:flutter_test/src/binding.dart:1183:19)
#19     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:370:5)
#20     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1146:15)
#21     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1083:9)
#22     AutomatedTestWidgetsFlutterBinding.pump.<anonymous closure> (package:flutter_test/src/binding.dart:1050:9)
#25     TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:71:41)
#26     AutomatedTestWidgetsFlutterBinding.pump (package:flutter_test/src/binding.dart:1037:27)
#27     WidgetTester.pump.<anonymous closure> (package:flutter_test/src/widget_tester.dart:608:53)
#30     TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:71:41)
#31     WidgetTester.pump (package:flutter_test/src/widget_tester.dart:608:27)
#32     main.<anonymous closure> (file:///Users/tom/Main/yplusplus/frontend/yplusplus_core/test/hello.dart:79:20)
<asynchronous suspension>
<asynchronous suspension>
(elided 5 frames from dart:async and package:stack_trace)

════════════════════════════════════════════════════════════════════════════════════════════════════
══╡ EXCEPTION CAUGHT BY WIDGET INSPECTOR ╞══════════════════════════════════════════════════════════
The following assertion was thrown:
Looking up a deactivated widget's ancestor is unsafe.
At this point the state of the widget's element tree is no longer stable.
To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by
calling dependOnInheritedWidgetOfExactType() in the widget's didChangeDependencies() method.

When the exception was thrown, this was the stack:
#0      Element._debugCheckStateIsActiveForAncestorLookup.<anonymous closure> (package:flutter/src/widgets/framework.dart:4186:9)
#1      Element._debugCheckStateIsActiveForAncestorLookup (package:flutter/src/widgets/framework.dart:4200:6)
#2      Element.visitAncestorElements (package:flutter/src/widgets/framework.dart:4299:12)
#3      _describeRelevantUserCode (package:flutter/src/widgets/widget_inspector.dart:3051:13)
#4      _parseDiagnosticsNode (package:flutter/src/widgets/widget_inspector.dart:2974:12)
#5      debugTransformDebugCreator (package:flutter/src/widgets/widget_inspector.dart:2950:21)
#6      _FlutterErrorDetailsNode.builder (package:flutter/src/foundation/assertions.dart:1291:31)
#7      DiagnosticableNode.getProperties (package:flutter/src/foundation/diagnostics.dart:3009:105)
#8      TextTreeRenderer._debugRender (package:flutter/src/foundation/diagnostics.dart:1244:63)
#9      TextTreeRenderer.render (package:flutter/src/foundation/diagnostics.dart:1121:14)
#10     FlutterError.dumpErrorToConsole (package:flutter/src/foundation/assertions.dart:1014:13)
#11     _defaultTestExceptionReporter (package:flutter_test/src/test_exception_reporter.dart:32:16)
#12     TestWidgetsFlutterBinding._createTestCompletionHandler.<anonymous closure> (package:flutter_test/src/binding.dart:663:28)
#22     TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart)
<asynchronous suspension>
(elided 9 frames from dart:async, dart:async-patch, and package:stack_trace)

This exception was caught while trying to describe the user-relevant code of another error.
════════════════════════════════════════════════════════════════════════════════════════════════════
══╡ EXCEPTION CAUGHT BY WIDGET INSPECTOR ╞══════════════════════════════════════════════════════════
The following assertion was thrown:
Looking up a deactivated widget's ancestor is unsafe.
At this point the state of the widget's element tree is no longer stable.
To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by
calling dependOnInheritedWidgetOfExactType() in the widget's didChangeDependencies() method.

When the exception was thrown, this was the stack:
#0      Element._debugCheckStateIsActiveForAncestorLookup.<anonymous closure> (package:flutter/src/widgets/framework.dart:4186:9)
#1      Element._debugCheckStateIsActiveForAncestorLookup (package:flutter/src/widgets/framework.dart:4200:6)
#2      Element.visitAncestorElements (package:flutter/src/widgets/framework.dart:4299:12)
#3      _describeRelevantUserCode (package:flutter/src/widgets/widget_inspector.dart:3051:13)
#4      _parseDiagnosticsNode (package:flutter/src/widgets/widget_inspector.dart:2974:12)
#5      debugTransformDebugCreator (package:flutter/src/widgets/widget_inspector.dart:2950:21)
#6      _FlutterErrorDetailsNode.builder (package:flutter/src/foundation/assertions.dart:1291:31)
#7      DiagnosticableNode.getProperties (package:flutter/src/foundation/diagnostics.dart:3009:105)
#8      TextTreeRenderer._debugRender (package:flutter/src/foundation/diagnostics.dart:1244:63)
#9      TextTreeRenderer.render (package:flutter/src/foundation/diagnostics.dart:1121:14)
#10     FlutterError.dumpErrorToConsole (package:flutter/src/foundation/assertions.dart:1014:13)
#11     _defaultTestExceptionReporter (package:flutter_test/src/test_exception_reporter.dart:32:16)
#12     TestWidgetsFlutterBinding._createTestCompletionHandler.<anonymous closure> (package:flutter_test/src/binding.dart:663:28)
#22     TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart)
<asynchronous suspension>
(elided 9 frames from dart:async, dart:async-patch, and package:stack_trace)

This exception was caught while trying to describe the user-relevant code of another error.
════════════════════════════════════════════════════════════════════════════════════════════════════
══╡ EXCEPTION CAUGHT BY WIDGET INSPECTOR ╞══════════════════════════════════════════════════════════
The following assertion was thrown:
Looking up a deactivated widget's ancestor is unsafe.
At this point the state of the widget's element tree is no longer stable.
To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by
calling dependOnInheritedWidgetOfExactType() in the widget's didChangeDependencies() method.

When the exception was thrown, this was the stack:
#0      Element._debugCheckStateIsActiveForAncestorLookup.<anonymous closure> (package:flutter/src/widgets/framework.dart:4186:9)
#1      Element._debugCheckStateIsActiveForAncestorLookup (package:flutter/src/widgets/framework.dart:4200:6)
#2      Element.visitAncestorElements (package:flutter/src/widgets/framework.dart:4299:12)
#3      _describeRelevantUserCode (package:flutter/src/widgets/widget_inspector.dart:3051:13)
#4      _parseDiagnosticsNode (package:flutter/src/widgets/widget_inspector.dart:2974:12)
#5      debugTransformDebugCreator (package:flutter/src/widgets/widget_inspector.dart:2950:21)
#6      _FlutterErrorDetailsNode.builder (package:flutter/src/foundation/assertions.dart:1291:31)
#7      DiagnosticableNode.emptyBodyDescription (package:flutter/src/foundation/diagnostics.dart:3006:77)
#8      TextTreeRenderer._debugRender (package:flutter/src/foundation/diagnostics.dart:1280:14)
#9      TextTreeRenderer.render (package:flutter/src/foundation/diagnostics.dart:1121:14)
#10     FlutterError.dumpErrorToConsole (package:flutter/src/foundation/assertions.dart:1014:13)
#11     _defaultTestExceptionReporter (package:flutter_test/src/test_exception_reporter.dart:32:16)
#12     TestWidgetsFlutterBinding._createTestCompletionHandler.<anonymous closure> (package:flutter_test/src/binding.dart:663:28)
#22     TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart)
<asynchronous suspension>
(elided 9 frames from dart:async, dart:async-patch, and package:stack_trace)

This exception was caught while trying to describe the user-relevant code of another error.
════════════════════════════════════════════════════════════════════════════════════════════════════
══╡ EXCEPTION CAUGHT BY WIDGET INSPECTOR ╞══════════════════════════════════════════════════════════
The following assertion was thrown:
Looking up a deactivated widget's ancestor is unsafe.
At this point the state of the widget's element tree is no longer stable.
To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by
calling dependOnInheritedWidgetOfExactType() in the widget's didChangeDependencies() method.

When the exception was thrown, this was the stack:
#0      Element._debugCheckStateIsActiveForAncestorLookup.<anonymous closure> (package:flutter/src/widgets/framework.dart:4186:9)
#1      Element._debugCheckStateIsActiveForAncestorLookup (package:flutter/src/widgets/framework.dart:4200:6)
#2      Element.visitAncestorElements (package:flutter/src/widgets/framework.dart:4299:12)
#3      _describeRelevantUserCode (package:flutter/src/widgets/widget_inspector.dart:3051:13)
#4      _parseDiagnosticsNode (package:flutter/src/widgets/widget_inspector.dart:2974:12)
#5      debugTransformDebugCreator (package:flutter/src/widgets/widget_inspector.dart:2950:21)
#6      _FlutterErrorDetailsNode.builder (package:flutter/src/foundation/assertions.dart:1291:31)
#7      DiagnosticableNode.emptyBodyDescription (package:flutter/src/foundation/diagnostics.dart:3006:77)
#8      TextTreeRenderer._debugRender (package:flutter/src/foundation/diagnostics.dart:1280:14)
#9      TextTreeRenderer.render (package:flutter/src/foundation/diagnostics.dart:1121:14)
#10     FlutterError.dumpErrorToConsole (package:flutter/src/foundation/assertions.dart:1014:13)
#11     _defaultTestExceptionReporter (package:flutter_test/src/test_exception_reporter.dart:32:16)
#12     TestWidgetsFlutterBinding._createTestCompletionHandler.<anonymous closure> (package:flutter_test/src/binding.dart:663:28)
#22     TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart)
<asynchronous suspension>
(elided 9 frames from dart:async, dart:async-patch, and package:stack_trace)

This exception was caught while trying to describe the user-relevant code of another error.
════════════════════════════════════════════════════════════════════════════════════════════════════

Test failed. See exception logs above.
The test description was: hi
no error
latest

A shorter reproducible sample, if you are interested:

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  testWidgets('hi', (tester) async {
    const imageData =
        'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=';

    final outerListenable = ValueNotifier<int>(0);
    final innerListenable = ValueNotifier<int>(0);

    var imageLoaded = false;
    var image = MemoryImage(base64Decode(imageData));

    Future<void> runAsyncAndIdle() async {
      for (var i = 0; i < 20; ++i) {
        await tester.runAsync(() => Future<void>.delayed(Duration.zero));
        await tester.idle();
      }
    }

    await tester.pumpWidget(ValueListenableBuilder(
      valueListenable: outerListenable,
      builder: (_, __, ___) => Image(
        image: image,
        frameBuilder: (_, child, __, ___) {
          if (((child as Semantics).child! as RawImage).image != null) imageLoaded = true;
          return LayoutBuilder(
            builder: (_, __) => ValueListenableBuilder(
              valueListenable: innerListenable,
              builder: (_, __, ___) => KeyedSubtree(
                key: UniqueKey(),
                child: child,
              ),
            ),
          );
        },
      ),
    ));

    while (!imageLoaded) {
      await runAsyncAndIdle();
      await tester.pump();
    }

    image = MemoryImage(base64Decode(imageData)); // imagine it is a new image
    outerListenable.value++;

    imageLoaded = false;
    while (!imageLoaded) {
      await runAsyncAndIdle();
      innerListenable.value++;
      await tester.pump();
    }
  });
}
@danagbemava-nc danagbemava-nc added the in triage Presently being triaged by the triage team label Aug 24, 2022
@danagbemava-nc danagbemava-nc changed the title Image has logical flow which disposes its image too early, causing errors such as "Cannot clone a disposed image" Image disposes its image too early, causing errors such as "Cannot clone a disposed image" Aug 24, 2022
@danagbemava-nc
Copy link
Member

Reproducible on stable and master using the tests in the initial post.

logs
build outer-Observer
build Image.frameBuilder peekChildImage=null
build LayoutBuilder peekChildImage=null
build inner-Observer peekChildImage=null
pump to wait for frameBuilderCountWithImage
build Image.frameBuilder peekChildImage=[1×1]
build LayoutBuilder peekChildImage=[1×1]
build inner-Observer peekChildImage=[1×1]
--- modify observable ---
--- pump ---
pump to wait for frameBuilderCountWithImage
build outer-Observer
build Image.frameBuilder peekChildImage=null
build inner-Observer peekChildImage=[1×1]
build LayoutBuilder peekChildImage=null
build inner-Observer peekChildImage=null
pump to wait for frameBuilderCountWithImage
build Image.frameBuilder peekChildImage=[1×1]
build inner-Observer peekChildImage=null
build LayoutBuilder peekChildImage=[1×1]
build inner-Observer peekChildImage=[1×1]
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following StateError was thrown building KeyedSubtree-[#4ded7]:
Bad state: Cannot clone a disposed image.
The clone() method of a previously-disposed Image was called. Once an Image object has been
disposed, it can no longer be used to create handles, as the underlying data may have been released.

When the exception was thrown, this was the stack:
#0      Image.clone (dart:ui/painting.dart:1808:7)
#1      RawImage.createRenderObject (package:flutter/src/widgets/basic.dart:5951:21)
#2      RenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5744:52)
...     Normal element mounting (10 frames)
#12     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3883:16)
#13     Element.updateChild (package:flutter/src/widgets/framework.dart:3606:20)
#14     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4920:16)
#15     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5060:11)
#16     Element.rebuild (package:flutter/src/widgets/framework.dart:4617:5)
#17     BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2687:19)
#18     AutomatedTestWidgetsFlutterBinding.drawFrame (package:flutter_test/src/binding.dart:1244:19)
#19     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:374:5)
#20     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1175:15)
#21     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1104:9)
#22     AutomatedTestWidgetsFlutterBinding.pump.<anonymous closure> (package:flutter_test/src/binding.dart:1093:9)
#25     TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:71:41)
#26     AutomatedTestWidgetsFlutterBinding.pump (package:flutter_test/src/binding.dart:1079:27)
#27     WidgetTester.pump.<anonymous closure> (package:flutter_test/src/widget_tester.dart:618:53)
#30     TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:71:41)
#31     WidgetTester.pump (package:flutter_test/src/widget_tester.dart:618:27)
#32     main.<anonymous closure> (file:///Users/nexus/projects/nevercode/bogus/test/widget_test.dart:79:20)
<asynchronous suspension>
<asynchronous suspension>
(elided 5 frames from dart:async and package:stack_trace)

════════════════════════════════════════════════════════════════════════════════════════════════════
Test failed. See exception logs above.
The test description was: hi

══╡ EXCEPTION CAUGHT BY WIDGET INSPECTOR ╞══════════════════════════════════════════════════════════
The following assertion was thrown:
Looking up a deactivated widget's ancestor is unsafe.
At this point the state of the widget's element tree is no longer stable.
To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by
calling dependOnInheritedWidgetOfExactType() in the widget's didChangeDependencies() method.

When the exception was thrown, this was the stack:
#0      Element._debugCheckStateIsActiveForAncestorLookup.<anonymous closure> (package:flutter/src/widgets/framework.dart:4261:9)
#1      Element._debugCheckStateIsActiveForAncestorLookup (package:flutter/src/widgets/framework.dart:4275:6)
#2      Element.visitAncestorElements (package:flutter/src/widgets/framework.dart:4383:12)
#3      _describeRelevantUserCode (package:flutter/src/widgets/widget_inspector.dart:3155:13)
#4      _parseDiagnosticsNode (package:flutter/src/widgets/widget_inspector.dart:3078:12)
#5      debugTransformDebugCreator (package:flutter/src/widgets/widget_inspector.dart:3054:21)
#6      _FlutterErrorDetailsNode.builder (package:flutter/src/foundation/assertions.dart:1300:31)
#7      DiagnosticableNode.getProperties (package:flutter/src/foundation/diagnostics.dart:2975:105)
#8      TextTreeRenderer._debugRender (package:flutter/src/foundation/diagnostics.dart:1278:63)
#9      TextTreeRenderer.render (package:flutter/src/foundation/diagnostics.dart:1151:14)
#10     FlutterError.dumpErrorToConsole (package:flutter/src/foundation/assertions.dart:1025:13)
#11     _defaultTestExceptionReporter (package:flutter_test/src/test_exception_reporter.dart:32:16)
#12     TestWidgetsFlutterBinding._createTestCompletionHandler.<anonymous closure> (package:flutter_test/src/binding.dart:682:28)
<asynchronous suspension>
<asynchronous suspension>
(elided 14 frames from dart:async and package:stack_trace)

This exception was caught while trying to describe the user-relevant code of another error.
════════════════════════════════════════════════════════════════════════════════════════════════════
══╡ EXCEPTION CAUGHT BY WIDGET INSPECTOR ╞══════════════════════════════════════════════════════════
The following assertion was thrown:
Looking up a deactivated widget's ancestor is unsafe.
At this point the state of the widget's element tree is no longer stable.
To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by
calling dependOnInheritedWidgetOfExactType() in the widget's didChangeDependencies() method.

When the exception was thrown, this was the stack:
#0      Element._debugCheckStateIsActiveForAncestorLookup.<anonymous closure> (package:flutter/src/widgets/framework.dart:4261:9)
#1      Element._debugCheckStateIsActiveForAncestorLookup (package:flutter/src/widgets/framework.dart:4275:6)
#2      Element.visitAncestorElements (package:flutter/src/widgets/framework.dart:4383:12)
#3      _describeRelevantUserCode (package:flutter/src/widgets/widget_inspector.dart:3155:13)
#4      _parseDiagnosticsNode (package:flutter/src/widgets/widget_inspector.dart:3078:12)
#5      debugTransformDebugCreator (package:flutter/src/widgets/widget_inspector.dart:3054:21)
#6      _FlutterErrorDetailsNode.builder (package:flutter/src/foundation/assertions.dart:1300:31)
#7      DiagnosticableNode.emptyBodyDescription (package:flutter/src/foundation/diagnostics.dart:2972:77)
#8      TextTreeRenderer._debugRender (package:flutter/src/foundation/diagnostics.dart:1316:14)
#9      TextTreeRenderer.render (package:flutter/src/foundation/diagnostics.dart:1151:14)
#10     FlutterError.dumpErrorToConsole (package:flutter/src/foundation/assertions.dart:1025:13)
#11     _defaultTestExceptionReporter (package:flutter_test/src/test_exception_reporter.dart:32:16)
#12     TestWidgetsFlutterBinding._createTestCompletionHandler.<anonymous closure> (package:flutter_test/src/binding.dart:682:28)
<asynchronous suspension>
<asynchronous suspension>
(elided 14 frames from dart:async and package:stack_trace)

This exception was caught while trying to describe the user-relevant code of another error.
════════════════════════════════════════════════════════════════════════════════════════════════════
✖ hi
Exited (1)
flutter doctor -v
[✓] Flutter (Channel stable, 3.0.5, on macOS 12.5 21G72 darwin-arm, locale en-GB)
    • Flutter version 3.0.5 at /Users/nexus/dev/sdks/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision f1875d570e (6 weeks ago), 2022-07-13 11:24:16 -0700
    • Engine revision e85ea0e79c
    • Dart version 2.17.6
    • DevTools version 2.12.2

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
    • Android SDK at /Users/nexus/Library/Android/sdk
    • Platform android-33, build-tools 33.0.0
    • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 13.4.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • CocoaPods version 1.11.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2021.2)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)

[✓] VS Code (version 1.70.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.46.0

[✓] Connected device (3 available)
    • iPhone 13 Pro (mobile) • 6E074BA5-191C-47D4-892F-FD96AFC34148 • ios            • com.apple.CoreSimulator.SimRuntime.iOS-15-5 (simulator)
    • macOS (desktop)        • macos                                • darwin-arm64   • macOS 12.5 21G72 darwin-arm
    • Chrome (web)           • chrome                               • web-javascript • Google Chrome 104.0.5112.101

[✓] HTTP Host Availability
    • All required HTTP hosts are available

• No issues found!
[✓] Flutter (Channel master, 3.1.0-0.0.pre.2443, on macOS 12.5 21G72 darwin-arm, locale en-GB)
    • Flutter version 3.1.0-0.0.pre.2443 on channel master at /Users/nexus/dev/sdks/flutters
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision e45031bf2a (2 hours ago), 2022-08-24 01:59:20 -0400
    • Engine revision 55c461f286
    • Dart version 2.19.0 (build 2.19.0-130.0.dev)
    • DevTools version 2.16.0

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
    • Android SDK at /Users/nexus/Library/Android/sdk
    • Platform android-33, build-tools 33.0.0
    • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 13.4.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 13F100
    • CocoaPods version 1.11.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2021.2)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)

[✓] VS Code (version 1.70.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.46.0

[✓] Connected device (3 available)
    • iPhone 13 Pro (mobile) • 6E074BA5-191C-47D4-892F-FD96AFC34148 • ios            • com.apple.CoreSimulator.SimRuntime.iOS-15-5 (simulator)
    • macOS (desktop)        • macos                                • darwin-arm64   • macOS 12.5 21G72 darwin-arm
    • Chrome (web)           • chrome                               • web-javascript • Google Chrome 104.0.5112.101

[✓] HTTP Host Availability
    • All required HTTP hosts are available

• No issues found!

@danagbemava-nc danagbemava-nc added c: crash Stack traces logged to the console framework flutter/packages/flutter repository. See also f: labels. a: images Loading, displaying, rendering images has reproducible steps The issue has been confirmed reproducible and is ready to work on found in release: 3.0 Found to occur in 3.0 found in release: 3.1 Found to occur in 3.1 and removed in triage Presently being triaged by the triage team labels Aug 24, 2022
@fzyzcjy
Copy link
Contributor Author

fzyzcjy commented Aug 24, 2022

@danagbemava-nc Thanks for the reply. Indeed I have PR it: #110131

@danagbemava-nc danagbemava-nc added the r: fixed Issue is closed as already fixed in a newer version label Aug 29, 2022
@github-actions
Copy link

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 -v and a minimal reproduction of the issue.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 12, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
a: images Loading, displaying, rendering images c: crash Stack traces logged to the console found in release: 3.0 Found to occur in 3.0 found in release: 3.1 Found to occur in 3.1 framework flutter/packages/flutter repository. See also f: labels. has reproducible steps The issue has been confirmed reproducible and is ready to work on r: fixed Issue is closed as already fixed in a newer version
Projects
None yet
2 participants