-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Description
I was attempting to reproduce a failed assertion thrown on Flutter for web (Failed assertion: 'node._relayoutBoundary == _relayoutBoundary': is not true.), and I arrived to a similar (but not identical*) crash happening both on Web and Android. Couldn't test on iOS.
Steps to Reproduce
- Run the app on this Gist
- After ~1000ms, look at your IDE console, the assertion will have failed
Expected behavior
- All SizedBoxes go to size 0x0 without throwing an assertion error.
Actual behavior
- The second SizedBox inside the LayoutBuilder fails the assertion.
What have I tried?
While I looked at this, a few things seemed to alleviate the issue (from more general to more into the rabbit hole):
- pausing initialization of the web app until the iframe was made visible (physicalSize > 0x0)
- noop'ing drawFrame when inside a hidden iframe
- preventing drawFrame from doing
layoutwhen inside a hidden iframe - ...going up the
layoutcall stack - changing how RenderObjects would select their relayoutBoundary when inside a 0x0 container; it seemed than the problematic ones picked their parent's and then they would never get laid-out again, then the assertion would fail...
It seems the LayoutBuilder is making some bad constraint choices when rendered in a 0x0 container, which breaks layout later on.
Logs
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following assertion was thrown building LayoutBuilder:
line 1348 pos 14:
'node._relayoutBoundary == _relayoutBoundary': is not true.
Either the assertion indicates an error in the framework itself, or we should provide substantially
more information in this error message to help you determine and fix the underlying cause.
In either case, please report this assertion by filing a bug on GitHub:
https://github.com/flutter/flutter/issues/new?template=BUG.md
When the exception was thrown, this was the stack:
#2 RenderObject._debugSubtreeRelayoutRootAlreadyMarkedNeedsLayout (package:flutter/src/rendering/object.dart:1348:14)
#3 RenderObject.markNeedsLayout (package:flutter/src/rendering/object.dart:1398:14)
#4 RenderBox.markNeedsLayout (package:flutter/src/rendering/box.dart:2048:11)
#5 RenderObject.markParentNeedsLayout (package:flutter/src/rendering/object.dart:1432:14)
#6 RenderObject.markNeedsLayout (package:flutter/src/rendering/object.dart:1403:7)
#7 RenderBox.markNeedsLayout (package:flutter/src/rendering/box.dart:2048:11)
#8 RenderConstrainedBox.additionalConstraints= (package:flutter/src/rendering/proxy_box.dart:209:5)
#9 SizedBox.updateRenderObject (package:flutter/src/widgets/basic.dart:2024:18)
#10 RenderObjectElement.update (package:flutter/src/widgets/framework.dart:4726:12)
#11 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:5097:11)
#12 Element.updateChild (package:flutter/src/widgets/framework.dart:2876:15)
#13 RenderObjectElement.updateChildren (package:flutter/src/widgets/framework.dart:4817:32)
#14 MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:5208:17)
#15 Element.updateChild (package:flutter/src/widgets/framework.dart:2876:15)
#16 _LayoutBuilderElement._layout.<anonymous closure> (package:flutter/src/widgets/layout_builder.dart:120:18)
#17 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2320:19)
#18 _LayoutBuilderElement._layout (package:flutter/src/widgets/layout_builder.dart:109:11)
#19 RenderObject.invokeLayoutCallback.<anonymous closure> (package:flutter/src/rendering/object.dart:1715:58)
#20 PipelineOwner._enableMutationsToDirtySubtrees (package:flutter/src/rendering/object.dart:796:15)
#21 RenderObject.invokeLayoutCallback (package:flutter/src/rendering/object.dart:1715:13)
#22 _RenderLayoutBuilder.performLayout (package:flutter/src/widgets/layout_builder.dart:207:5)
#23 RenderObject.layout (package:flutter/src/rendering/object.dart:1619:7)
#24 RenderConstrainedBox.performLayout (package:flutter/src/rendering/proxy_box.dart:259:13)
#25 RenderObject.layout (package:flutter/src/rendering/object.dart:1619:7)
#26 MultiChildLayoutDelegate.layoutChild (package:flutter/src/rendering/custom_layout.dart:142:11)
#27 _ScaffoldLayout.performLayout (package:flutter/src/material/scaffold.dart:443:7)
#28 MultiChildLayoutDelegate._callPerformLayout (package:flutter/src/rendering/custom_layout.dart:212:7)
#29 RenderCustomMultiChildLayoutBox.performLayout (package:flutter/src/rendering/custom_layout.dart:356:14)
#30 RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:1496:7)
#31 PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:765:18)
#32 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:346:19)
#33 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:701:13)
#34 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:285:5)
#35 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1016:15)
#36 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:958:9)
#37 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:874:5)
#41 _invoke (dart:ui/hooks.dart:236:10)
#42 _drawFrame (dart:ui/hooks.dart:194:3)
(elided 5 frames from class _AssertionError and package dart:async)
════════════════════════════════════════════════════════════════════════════════════════════════════
flutter analyze
$ flutter analyze
Analyzing relayout_boundaries_android...
No issues found! (ran in 1.3s)
flutter doctor -v
$ flutter doctor -v
[✓] Flutter (Channel stable, v1.7.8+hotfix.4, on Linux, locale en_US.UTF-8)
• Flutter version 1.7.8+hotfix.4 at /path/to/lib/flutter
• Framework revision 20e59316b8 (5 weeks ago), 2019-07-18 20:04:33 -0700
• Engine revision fee001c93f
• Dart version 2.4.0
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.1)
• Android SDK at /path/to/Android/Sdk
• Android NDK location not configured (optional; useful for native profiling
support)
• Platform android-stable, build-tools 29.0.1
• Java binary at: /path/to/jre/bin/java
• Java version OpenJDK Runtime Environment (build
1.8.0_152-release-1343-b16-5323222)
• All Android licenses accepted.
[✓] Android Studio (version 3.4)
• Android Studio at /path/to/android-studio
• Flutter plugin version 38.2.1
• Dart plugin version 183.6270
• Java version OpenJDK Runtime Environment (build
1.8.0_152-release-1343-b16-5323222)
[✓] Connected device (1 available)
• Android SDK built for x86 • emulator-5554 • android-x86 • Android 7.1.1 (API 25)
(emulator)
• No issues found!
* The difference between this crash and the one I was originally investigating is that the one in the gallery happens when going from a 0x0 physicalWindow (iframe element with display:none) to a normally sized physicalWindow.
This bug seems to be the opposite, but I couldn't find a way to "fake" a 0x0 physicalWindow in my Android app. The code path is similar enough to make me believe that this is the same bug that I was chasing, only manifesting in a slightly different way.