Skip to content

[web] SelectionArea in MaterialApp.builder throws "RenderBox was not laid out" on startup (refile of #191508) #193287

Open

Description

@feldgendler

Steps to reproduce

  1. flutter create --platforms=web bug
  2. Replace lib/main.dart with the code sample below.
  3. flutter run -d chrome

This is a refile of #191508, which was closed automatically while it was labelled "waiting for response", although a minimal repro had been posted there (the code sample below is that repro). It still reproduces on stable 3.47.5 (Chrome 154) and on master at 434cd53 (2026-09-24).

Expected results

No exception on startup.

Actual results

On every load, an assertion is thrown while dispatching WidgetsBindingObserver.didChangeViewFocus:

RenderBox was not laid out: RenderStack#1d01a NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE

It comes from _ViewState.didChangeViewFocus → findFirstFocus → FocusNode.rect → RenderBox.size, before the first frame has been laid out (full stack in the logs below). In a release --wasm build the same error is logged as Bad state: RenderBox was not laid out: minified:Class…. The app works normally afterwards.

Workaround: wrapping the route instead (home: SelectionArea(child: ...), with no Overlay in builder) does not throw. The Overlay in builder without the SelectionArea does not throw either.

Code sample

Code sample
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: const Scaffold(body: Center(child: Text('hello'))),
      builder: (context, child) => Overlay(
        initialEntries: [
          OverlayEntry(builder: (context) => SelectionArea(child: child ?? const SizedBox.shrink())),
        ],
      ),
    );
  }
}

Screenshots or Video

No response

Logs

Logs

flutter run -d chrome (debug, DDC), Flutter 3.47.5, Chrome 154:

══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following assertion was thrown while dispatching notifications for
WidgetsBindingObserver.didChangeViewFocus:
Assertion failed:
file://<flutter>/packages/flutter/lib/src/rendering/box.dart:2251:12
hasSize
"RenderBox was not laid out: RenderStack#1d01a NEEDS-LAYOUT NEEDS-PAINT
NEEDS-COMPOSITING-BITS-UPDATE"

When the exception was thrown, this was the stack:
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 274:3       throw_
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 44:3        assertFailed
package:flutter/src/rendering/box.dart 2251:12                                    get size
package:flutter/src/rendering/box.dart 2437:44                                    get semanticBounds
package:flutter/src/widgets/focus_manager.dart 871:13                             get rect
package:flutter/src/widgets/focus_traversal.dart 1399:18                          new
package:flutter/src/widgets/focus_traversal.dart 1580:43                          <fn>
package:flutter/src/widgets/focus_traversal.dart 1579:41                          sort
package:flutter/src/widgets/focus_traversal.dart 1709:7                           sortDescendants
package:flutter/src/widgets/focus_traversal.dart 514:55                           _sortAllDescendants
package:flutter/src/widgets/focus_traversal.dart 338:9                            [_findInitialFocus]
package:flutter/src/widgets/focus_traversal.dart 299:12                           findFirstFocus
package:flutter/src/widgets/view.dart 254:33                                      didChangeViewFocus
package:flutter/src/widgets/binding.dart 1355:17                                  handleViewFocusChanged
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 118:77  tear
lib/_engine/engine/platform_dispatcher.dart 1748:5                                invoke1
lib/_engine/engine/platform_dispatcher.dart 206:5                                 invokeOnViewFocusChange
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 118:77  tear
lib/_engine/engine/platform_dispatcher/view_focus_binding.dart 109:23             [_handleFocusChange]
lib/_engine/engine/platform_dispatcher/view_focus_binding.dart 54:5               <fn>
dart-sdk/lib/async/zone.dart 1034:54                                              runUnary
dart-sdk/lib/async/zone.dart 989:26                                               <fn>
dart-sdk/lib/_internal/js_dev_runtime/patch/js_allow_interop_patch.dart 218:27    _callDartFunctionFast1
dart-sdk/lib/_internal/js_dev_runtime/patch/js_allow_interop_patch.dart 78:15     ret
lib/_engine/engine/dom.dart 518:8                                                 DomElement.focusWithoutScroll
lib/_engine/engine/platform_dispatcher/view_focus_binding.dart 45:24              changeViewFocus
lib/_engine/engine/platform_dispatcher.dart 215:5                                 requestViewFocusChange
package:flutter/src/widgets/view.dart 233:29                                      [_scopeFocusChangeListener]
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 118:77  tear
package:flutter/src/foundation/change_notifier.dart 435:24                        notifyListeners
package:flutter/src/widgets/focus_manager.dart 1139:5                             [_notify]
package:flutter/src/widgets/focus_manager.dart 2011:11                            applyFocusChangesIfNeeded
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 118:77  tear
dart-sdk/lib/async/schedule_microtask.dart 40:34                                  _microtaskLoop
dart-sdk/lib/async/schedule_microtask.dart 49:5                                   _startMicrotaskLoop
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 118:77  tear
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 183:69               <fn>
════════════════════════════════════════════════════════════════════════════════════════════════════

Flutter Doctor output

Doctor output
[✓] Flutter (Channel stable, 3.47.5, on macOS 27.0 26A428 darwin-arm64, locale en-GB) [18.0s]
    • Flutter version 3.47.5 on channel stable at ~/.local/share/mise/http-tarballs/853f502e6161aaf03f395ae268c089f77546297338dd033b403474e8af39e7b8_strip_1
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 6a19cca564 (7 days ago), 2026-09-17 14:13:22 -0400
    • Engine revision af7e796e16
    • Dart version 3.13.4
    • DevTools version 2.60.0
    • Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios, cli-animations, enable-native-assets, enable-record-use, enable-swift-package-manager, omit-legacy-version-file, enable-lldb-debugging, enable-uiscene-migration

[✓] Android toolchain - develop for Android devices (Android SDK version 36.1.0) [19.7s]
    • Android SDK at ~/Library/Android/sdk
    • Emulator version 36.2.11.0 (build_id 14212360) (CL:N/A)
    • Platform android-36, build-tools 36.1.0
    ! Multiple adb binaries found. This can cause conflicts and device detection issues:
        - ~/Library/Android/sdk/platform-tools/adb
        - /opt/homebrew/Caskroom/android-platform-tools/37.0.1/platform-tools/adb
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
      This is the JDK bundled with the latest Android Studio installation on this machine.
      To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
    • Java version OpenJDK Runtime Environment (build 25.0.3+-15898627-b508.16)
    • All Android licenses accepted.

[!] Xcode - develop for iOS and macOS (Xcode 27.0) [20.1s]
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 27A266a
    ✗ Unable to get list of installed Simulator runtimes.
    ! CocoaPods not installed.
        CocoaPods is a package manager for iOS or macOS platform code.
        Without CocoaPods, plugins will not work on iOS or macOS.
        For more info, see https://flutter.dev/to/platform-plugins
      For installation instructions, see https://guides.cocoapods.org/using/getting-started.html#installation

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

[✓] Connected device (2 available) [12.2s]
    • macOS (desktop) • macos  • darwin-arm64   • macOS 27.0 26A428 darwin-arm64
    • Chrome (web)    • chrome • web-javascript • Google Chrome 154.0.8037.58

[✓] Network resources [543ms]
    • All expected network resources are available.

! Doctor found issues in 1 category.

Activity

  1. BartSimpson001 commented on Sep 24, 2026

    @BartSimpson001

    I’m investigating this issue and tracing the focus and layout lifecycle to identify the root cause. I’ll share my findings once I have more information.

  2. suryaKommana2662 commented on Sep 25, 2026

    @suryaKommana2662
    Contributor

    @feldgendler Thanks for the report. I was able to reproduce the issue locally on Chrome using the provided reproduction. routing to the team-text-input for further investigation.

    The application launches successfully, but the following assertion is thrown during WidgetsBindingObserver.didChangeViewFocus:

    Assertion failed:
    packages/flutter/lib/src/rendering/box.dart:2256:12
    hasSize
    "RenderBox was not laid out: RenderStack#b70de NEEDS-LAYOUT NEEDS-PAINT
    NEEDS-COMPOSITING-BITS-UPDATE"
    

    The stack trace includes:

    package:flutter/src/rendering/box.dart 2256:12
    package:flutter/src/rendering/box.dart 2442:44
    package:flutter/src/widgets/focus_manager.dart 868:13
    package:flutter/src/widgets/focus_traversal.dart 1454:18
    package:flutter/src/widgets/focus_traversal.dart 1634:43
    package:flutter/src/widgets/focus_traversal.dart 1763:7
    package:flutter/src/widgets/focus_traversal.dart 338:9
    package:flutter/src/widgets/focus_traversal.dart 299:12
    package:flutter/src/widgets/view.dart 254:33
    package:flutter/src/widgets/binding.dart 1359:17
    

    Flutter Doctor Output

    [✓] Flutter (Channel stable, 3.47.5, on macOS 27.0 26A428 darwin-arm64, locale en-IN) [730ms]
        • Flutter version 3.47.5 on channel stable at /Users/suryakommana/develop/flutter
        • Upstream repository https://github.com/flutter/flutter.git
        • Framework revision 6a19cca564 (8 days ago), 2026-09-17 14:13:22 -0400
        • Engine revision af7e796e16
        • Dart version 3.13.4
        • DevTools version 2.60.0
        • Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios, cli-animations, enable-native-assets,
          enable-record-use, enable-swift-package-manager, omit-legacy-version-file, enable-lldb-debugging, enable-uiscene-migration
    
    [✓] Android toolchain - develop for Android devices (Android SDK version 36.0.0) [1,166ms]
        • Android SDK at /Users/suryakommana/Library/Android/sdk
        • Emulator version 37.1.11.0 (build_id 15917651) (CL:N/A)
        • Platform android-37.0, build-tools 36.0.0
        • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
          This is the JDK bundled with the latest Android Studio installation on this machine.
          To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
        • Java version OpenJDK Runtime Environment (build 25.0.2+-15348964-b329.117)
        • All Android licenses accepted.
    
    [✓] Xcode - develop for iOS and macOS (Xcode 27.0) [886ms]
        • Xcode at /Applications/Xcode.app/Contents/Developer
        • Build 27A266a
        • CocoaPods version 1.17.0
    
    [✓] Chrome - develop for the web [4ms]
        • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
    
    [✓] Connected device (4 available) [9.4s]
        • sdk gphone16k arm64 (mobile) • emulator-5554                        • android-arm64  • Android 17 (API 37) (emulator)
        • iPhone 18 Pro (mobile)       • D80F2104-E911-4251-BEDD-E67D9B7EBF58 • ios            • com.apple.CoreSimulator.SimRuntime.iOS-27-0 (simulator)
        • macOS (desktop)              • macos                                • darwin-arm64   • macOS 27.0 26A428 darwin-arm64
        • Chrome (web)                 • chrome                               • web-javascript • Google Chrome 153.0.8010.54
    
    [✓] Network resources [927ms]
        • All expected network resources are available.
    
    • No issues found!
  3. added
    a: text inputEntering text in a text field or keyboard related problems
    f: selectionSelectableRegion, SelectionArea, SelectionContainer, Selectable, and related APIs
    fyi-webFor the attention of Web platform team
    and removed
    in triagePresently being triaged by the triage team
    on Sep 25, 2026
  4. mdebbar commented on Sep 30, 2026

    @mdebbar
    Contributor

    Are you seeing this issue on other platforms too? This seems like a framework issue, not a web one.

  5. feldgendler commented on Sep 30, 2026

    @feldgendler
    Author

    Tested on macOS desktop and Android (3.47.5): the repro doesn't throw there. But it's not web-specific code. It reproduces on the Dart VM in a plain flutter test when a view-focus event (focused, forward) arrives after build and before the first layout:

    testWidgets('forward view focus before the first layout', (tester) async {
      await tester.pumpWidget(const MyApp(), phase: EnginePhase.build);
      tester.binding.handleViewFocusChanged(ViewFocusEvent(
        viewId: tester.view.viewId,
        state: ViewFocusState.focused,
        direction: ViewFocusDirection.forward,
      ));
      await tester.pump();
    });

    This throws the same RenderBox was not laid out from _ViewState.didChangeViewFocus → findFirstFocus → ReadingOrderTraversalPolicy.sort. The two variants from the issue (no SelectionArea, or SelectionArea around home) pass. The web is where it shows because the web engine runs the warm-up frame's beginFrame and drawFrame in separate timers, so the view-focus event from the startup focus change lands before layout. macOS sends direction undefined, which skips findFirstFocus, and Android/iOS don't send view-focus events. So this looks like a framework issue in didChangeViewFocus / the traversal policy reading rects of nodes that aren't laid out yet.

  6. 1 remaining item

  7. added
    P2Important issues not at the top of the work list
    a: text inputEntering text in a text field or keyboard related problems
    f: selectionSelectableRegion, SelectionArea, SelectionContainer, Selectable, and related APIs
    fyi-webFor the attention of Web platform team
    triaged-webTriaged by Web platform team
    and removed
    f: selectionSelectableRegion, SelectionArea, SelectionContainer, Selectable, and related APIs
    triaged-webTriaged by Web platform team
    fyi-webFor the attention of Web platform team
    on Oct 1, 2026
  8. dorklein commented on Nov 13, 2026

    @dorklein

    Note

    🤖 Claude Opus 5.5 responding on behalf of Dor Klein

    Still reproduces on stable 3.50.0, and it isn't specific to SelectionArea or Overlay: a plain Focus in MaterialApp.builder is enough. The node that isn't laid out is then RenderSemanticsAnnotations.

    With the VM test from the comment above (same results on 3.50.0 and 3.47.8):

    MaterialApp.builder Result
    none passes
    issue sample (Overlay + SelectionArea) RenderBox was not laid out: RenderSemanticsAnnotations
    (context, child) => Focus(child: Stack(children: [child!])) same error
    same with Focus(autofocus: true, ...) same error
    MaterialApp.router, no builder passes

    In a real web app (3.50.0, debug), the trace also shows where the early view-focus event comes from: the framework's own first focus change, which the web engine sends back synchronously.

    FocusManager.applyFocusChangesIfNeeded      (microtask)
    → _ViewState._scopeFocusChangeListener      widgets/view.dart:233
    → PlatformDispatcher.requestViewFocusChange
    → ViewFocusBinding.changeViewFocus → focusWithoutScroll   (synchronous focusin)
    → _ViewState.didChangeViewFocus (forward)   widgets/view.dart:254
    → findFirstFocus → _sortAllDescendants → FocusNode.rect → RenderBox.size
    

    My reading: any app with a focus node above the navigator in builder likely hits this on every web load.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

P2Important issues not at the top of the work lista: text inputEntering text in a text field or keyboard related problemsf: selectionSelectableRegion, SelectionArea, SelectionContainer, Selectable, and related APIsteam-text-inputOwned by Text Input teamtriaged-text-inputTriaged by Text Input team

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions