Skip to content

[Regression] OverlayPortal semantics bounds/coordinates corrupted after fccfa978a97 #182604

Closed

Description

@divan

Steps to reproduce

Steps to reproduce described here duobaseio/forui#854, as this bug was discovered in an attempt to test Flutter app that uses forui library using Maestro testing framework. Tests were failing after showing popover (date field, calendar) etc, and visual inspection in Maestro Studio showed werid semantic node coordnate shrinking (red borders outlines how Maestro "sees" semantic nodes).

Further discussion with forui devs and analysis of Flutter's commits revealed the likely culprit: fccfa97

Further test with pre-commit and post-commit version of Flutter confirmed that bug doesn't exist in pre-commit version. More details and video here - duobaseio/forui#854 (comment)

Image

After clicking outside of the field (to dismiss popup):

Image

Expected results

Semantic nodes coordinates are not corrupted or shrinked..

Actual results

Semantic nodes' coordinates are corrupted, making further testing impossible.

Code sample

See linked forui issue for steps to reproduce:

Code sample

pubspec.yaml

name: forui_repro
environment:
  sdk: '>=3.0.0 <4.0.0'
dependencies:
  flutter:
    sdk: flutter
  forui: 0.18.1

main.dart

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

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

class App extends StatelessWidget {
  const App({super.key});
  @override
  Widget build(BuildContext context) => MaterialApp(
        home: FScaffold(
          child: Center(
            child: const SizedBox(
                width: 300, child: FDateField(label: Text('Inline Dates'))),
          ),
        ),
      );
}

Screenshots or Video

Screenshots / Video demonstration
Screen.Recording.2026-02-18.at.17.58.08.mov

Testing it with a bit more complex MVE:

pre-commit version:

Screen.Recording.2026-02-19.at.12.14.37.mov

post-commit version

Screen.Recording.2026-02-19.at.12.16.41.mov

Logs

Logs
[Paste your logs here]

Flutter Doctor output

Doctor output

pre-commit version

[!] Flutter (Channel [user-branch], 3.42.0-0.0.pre, on macOS 26.2 25C56 darwin-arm64, locale en-US)
    ! Flutter version 3.42.0-0.0.pre on channel [user-branch] at /Users/divan/src/flutter_pre_fcc
      Currently on an unknown channel. Run `flutter channel` to switch to an official channel.
      If that doesn't fix the issue, reinstall Flutter by following instructions at
      https://flutter.dev/setup.
    ! Upstream repository unknown source is not a standard remote.
      Set environment variable "FLUTTER_GIT_URL" to unknown source to dismiss this error.
[✓] Android toolchain - develop for Android devices (Android SDK version 36.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 26.2)
[✓] Chrome - develop for the web
[✓] Connected device (4 available)
    ! Error: Browsing on the local area network for divan‘s iPad. Ensure the device is unlocked and
      attached with a cable or associated with the same local area network as this Mac.
      The device must be opted into Developer Mode to connect wirelessly. (code -27)
    ! Error: Browsing on the local area network for Ivan’s Apple Watch. Ensure the device is unlocked and
      discoverable via Bluetooth. (code -27)
    ! Error: Browsing on the local area network for Not Ivan‘s iPad. Ensure the device is unlocked and
      attached with a cable or associated with the same local area network as this Mac.
      The device must be opted into Developer Mode to connect wirelessly. (code -27)
    ! Error: Browsing on the local area network for Ivan’s iPhone. Ensure the device is unlocked and
      attached with a cable or associated with the same local area network as this Mac.
      The device must be opted into Developer Mode to connect wirelessly. (code -27)
[✓] Network resources

post-commit version

flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[!] Flutter (Channel [user-branch], 3.42.0-0.0.pre, on macOS 26.2 25C56 darwin-arm64, locale en-US)
    ! Flutter version 3.42.0-0.0.pre on channel [user-branch] at /Users/divan/src/flutter_pre_fcc
      Currently on an unknown channel. Run `flutter channel` to switch to an official channel.
      If that doesn't fix the issue, reinstall Flutter by following instructions at
      https://flutter.dev/setup.
    ! Upstream repository unknown source is not a standard remote.
      Set environment variable "FLUTTER_GIT_URL" to unknown source to dismiss this error.
[✓] Android toolchain - develop for Android devices (Android SDK version 36.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 26.2)
[✓] Chrome - develop for the web
[✓] Connected device (4 available)
    ! Error: Browsing on the local area network for divan‘s iPad. Ensure the device is unlocked and
      attached with a cable or associated with the same local area network as this Mac.
      The device must be opted into Developer Mode to connect wirelessly. (code -27)
    ! Error: Browsing on the local area network for Ivan’s Apple Watch. Ensure the device is unlocked and
      discoverable via Bluetooth. (code -27)
    ! Error: Browsing on the local area network for Not Ivan‘s iPad. Ensure the device is unlocked and
      attached with a cable or associated with the same local area network as this Mac.
      The device must be opted into Developer Mode to connect wirelessly. (code -27)
    ! Error: Browsing on the local area network for Ivan’s iPhone. Ensure the device is unlocked and
      attached with a cable or associated with the same local area network as this Mac.
      The device must be opted into Developer Mode to connect wirelessly. (code -27)
[✓] Network resources

Activity

  1. added
    c: regressionIt was better in the past than it is now
    has reproducible stepsThe issue has been confirmed reproducible and is ready to work on
    team-accessibilityOwned by Framework Accessibility team (i.e. responsible for accessibility code in flutter/flutter)
    on Feb 23, 2026
  2. mbcorona commented on Feb 23, 2026

    @mbcorona
    Member

    Hi @divan, thanks for the detailed report, labeling team-accessibility, and regression for further investigation.

  3. chunhtai commented on Feb 25, 2026

    @chunhtai
    Contributor

    I am not entirely sure whether the root cause is in flutter or in the testing library. The change introduced a different transform in Semantics node that is specific for children in traversal order, and there is different transform for children in hittest order because now the traversal tree and hittest tree may have different shape. It is possible which ever software calculate the bound is using the wrong transform.

    cc @QuncCccccc Can you take a look at this?

  4. added
    P2Important issues not at the top of the work list
    on Feb 25, 2026
  5. divan commented on Feb 27, 2026

    @divan
    Author

    I posted the link to the issue to Maestro discord chat as well, in case there are devs who might be willing to take a look at it as well.

  6. divan commented on Feb 27, 2026

    @divan
    Author

    @chunhtai here is one response from Maestro team support:

    Maestro doesn't calculate bounds. It reads the reported ones from the device.
    Try using the Accessibility Inspector that ships with Xcode. That should report the same bounds that Maestro sees.

    I haven't tried Xcode tool myself, but in the chat with forui dev I remember he said that observed the same behaviour in Xcode accesibility inspector.

    So it's most likely the Flutter's issue, and not the Maestro's one.

  7. Pante commented on Feb 27, 2026

    @Pante
    Contributor

    I haven't tried Xcode tool myself, but in the chat with forui dev I remember he said that observed the same behaviour in Xcode accesibility inspector.

    Just chipping in, but I can confirm that the issue persists with Xcode accesibility inspector.

    I also have an MVE that replicates the issue with just Materiel widgets: https://gist.github.com/Pante/d7b2d1755802bafab022180d6a373063.

  8. chunhtai commented on Feb 27, 2026

    @chunhtai
    Contributor

    gotcha, yeah that sounds like a flutter issue.

  9. QuncCccccc commented on Mar 3, 2026

    @QuncCccccc
    Contributor

    Thanks for providing the sample code to reproduce! The semantics tree from the framework side looks correct. So I'm wondering whether it's the engine side doesn't interpret data correctly? CC: @chunhtai

    flutter: SemanticsNode#0
    flutter: │ Rect.fromLTRB(0.0, 0.0, 1668.0, 2388.0)
    flutter: │
    flutter: └─SemanticsNode#1
    flutter: │ Rect.fromLTRB(0.0, 0.0, 834.0, 1194.0) scaled by 2.0x
    flutter: │ textDirection: ltr
    flutter: │
    flutter: └─SemanticsNode#2
    flutter: │ Rect.fromLTRB(0.0, 0.0, 834.0, 1194.0)
    flutter: │ sortKey: OrdinalSortKey#caba3(order: 0.0)
    flutter: │
    flutter: └─SemanticsNode#3
    flutter: │ Rect.fromLTRB(0.0, 0.0, 834.0, 1194.0)
    flutter: │ flags: scopesRoute
    flutter: │
    flutter: ├─SemanticsNode#4
    flutter: │ │ Rect.fromLTRB(340.7, 539.0, 493.3, 587.0)
    flutter: │ │ traversalParentIdentifier: _OverlayPortalState#d4204
    flutter: │ │
    flutter: │ ├─SemanticsNode#5
    flutter: │ │ Rect.fromLTRB(0.0, 0.0, 152.5, 48.0)
    flutter: │ │ actions: tap
    flutter: │ │ flags: isButton, hasEnabledState, isEnabled, isFocusable
    flutter: │ │ label: "Hide (setState)"
    flutter: │ │ textDirection: ltr
    flutter: │ │
    flutter: │ └─SemanticsNode#8
    flutter: │ │ Rect.fromLTRB(0.0, 0.0, 834.0, 1194.0)
    flutter: │ │ traversalChildIdentifier: _OverlayPortalState#d4204
    flutter: │ │
    flutter: │ └─SemanticsNode#9
    flutter: │ │ Rect.fromLTRB(340.7, 587.0, 540.7, 675.0)
    flutter: │ │ label:
    flutter: │ │ "WithSetState Item 1
    flutter: │ │ WithSetState Item 2"
    flutter: │ │ textDirection: ltr
    flutter: │ │
    flutter: │ └─SemanticsNode#10
    flutter: │ Rect.fromLTRB(56.7, 40.0, 143.3, 88.0)
    flutter: │ actions: tap
    flutter: │ flags: isButton, hasEnabledState, isEnabled, isFocusable
    flutter: │ label: "Close"
    flutter: │ textDirection: ltr

    flutter: │
    flutter: └─SemanticsNode#6
    flutter: │ Rect.fromLTRB(327.4, 607.0, 506.6, 655.0)
    flutter: │ traversalParentIdentifier: _OverlayPortalState#7d113
    flutter: │
    flutter: └─SemanticsNode#7
    flutter: Rect.fromLTRB(0.0, 0.0, 179.2, 48.0)
    flutter: actions: tap
    flutter: flags: isButton, hasEnabledState, isEnabled, isFocusable
    flutter: label: "Show (no setState)"
    flutter: textDirection: ltr

  10. added
    team-iosOwned by iOS platform team
    and removed
    team-accessibilityOwned by Framework Accessibility team (i.e. responsible for accessibility code in flutter/flutter)
    on Mar 3, 2026
  11. flutter-triage-bot commented on Mar 3, 2026

    @flutter-triage-bot

    The triaged-accessibility label is irrelevant if there is no team-accessibility label or fyi-accessibility label.

  12. okorohelijah commented on Mar 12, 2026

    @okorohelijah
    Contributor

    @QuncCccccc from triage: were you able to check if it works when the pr is reverted?

  13. divan commented on Mar 30, 2026

    @divan
    Author

    Any progress on this?.

  14. MrRobot2002 commented on Apr 9, 2026

    @MrRobot2002

    The same issue happens to me on an angular application. The save to files button coordinates are way off, and impossible to test.

    Image
  15. Jjagg commented on Jun 8, 2026

    @Jjagg
    Contributor

    Here's another demo of this issue (recorded on an iPhone 17 Pro Simulator running iOS 26.1):

    Screen.Recording.2026-06-08.at.14.42.41.mov

    Maybe this is useful to know: the only elements I needed for this repro were MaterialApp.router and OverlayPortal. Using MaterialApp(home: ReproScreen()) did not reproduce the issue.
    I can also reconfirm that the Semantics tree looked correct.

    Looking at the commit that introduced the bug (fccfa97); it seems like the new transform behavior was not implement in the ios accessibility_bridge.mm.

    Here's the main.dart of the repro I used for the video:

    Details
    import 'package:flutter/material.dart';
    
    void main() => runApp(ReproApp());
    
    class ReproApp extends StatelessWidget {
      ReproApp({super.key});
    
      final _MinimalRouterDelegate _routerDelegate = _MinimalRouterDelegate();
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp.router(showSemanticsDebugger: false, routerDelegate: _routerDelegate);
      }
    }
    
    class _MinimalRouterDelegate extends RouterDelegate<Object>
        with ChangeNotifier, PopNavigatorRouterDelegateMixin<Object> {
      @override
      final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
    
      @override
      Widget build(BuildContext context) {
        return Navigator(
          key: navigatorKey,
          pages: const [MaterialPage(child: ReproScreen())],
          onDidRemovePage: (_) {},
        );
      }
    
      @override
      Future<void> setNewRoutePath(Object configuration) async {}
    }
    
    class ReproScreen extends StatefulWidget {
      const ReproScreen({super.key});
    
      @override
      State<ReproScreen> createState() => _ReproScreenState();
    }
    
    class _ReproScreenState extends State<ReproScreen> {
      final OverlayPortalController _controller = OverlayPortalController();
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text('OverlayPortal a11y repro'),
            actions: [
              OverlayPortal(
                controller: _controller,
                overlayChildBuilder: (context) => GestureDetector(
                  onTap: _controller.hide,
                  child: ColoredBox(
                    color: Colors.deepPurple.shade700,
                    child: const SizedBox.expand(
                      child: Center(
                        child: Text('Tap anywhere to dismiss', style: TextStyle(color: Colors.white)),
                      ),
                    ),
                  ),
                ),
              ),
            ],
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const Text(
                  'Steps:\n'
                  '1. Tap the bug button to show the overlay\n'
                  '2. Tap anywhere to dismiss it.\n'
                  '3. Re-inspect: the a11y nodes are transformed,',
                  textAlign: TextAlign.center,
                ),
                IconButton(icon: const Icon(Icons.bug_report), tooltip: 'Open overlay', onPressed: _controller.show),
              ],
            ),
          ),
        );
      }
    }
  16. tpaik18 commented on Jun 8, 2026

    @tpaik18

    Would love if priority could be bumped up on this; this issue appears to break our XCUITest for our app when upgrading Flutter from 3.38 to current version.

  17. github-actions commented on Sep 17, 2026

    @github-actions

    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.

  18. locked as resolved and limited conversation to collaborators on Sep 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work listc: regressionIt was better in the past than it is nowhas reproducible stepsThe issue has been confirmed reproducible and is ready to work onteam-iosOwned by iOS platform teamtriaged-iosTriaged by iOS platform team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions