Skip to content

[iOS] DropdownMenu selection tears down the entire iOS accessibility tree when the app uses the Router API (go_router / MaterialApp.router) #187611

Open

Description

@elitree

Steps to reproduce

Note: as you can tell, I had a lot of help from Claude on this one. It's very similar to #186582, but is different enough (specific to a Gorouter setup) that I'm entering a separate bug - feel free to close as a duplicate if that's the path forward. It's not clear to me whether or not the PR to fix the existing issue will fix this one too.

Clonable repro: https://github.com/elitree/dropdown_gorouter_repro

  1. Run on an iOS simulator or device (flutter run) with useGoRouter = true.
  2. Open Xcode → Open Developer Tool → Accessibility Inspector and target the simulator/device.
  3. Inspect the page — the marker Text, the button, and the dropdown are all present in the accessibility hierarchy.
  4. Tap the DropdownMenu and select any entry.
  5. Re-inspect: the accessibility tree is now empty — the marker Text and the button are gone too, not just the menu. It stays collapsed for the rest of the session.

Isolation

Bisected from a large production app down to this minimal repro, running the same Accessibility Inspector before/after check at each step.

The single differing variable is the routing API:

Host Identical page Result after selection
MaterialApp.router + go_router ✅ Tree collapses
plain MaterialApp (Navigator 1.0) ✅ Tree survives

Ruled out (collapse still reproduces without them, or they make no difference):
Google Maps / UiKitView platform views, showModalBottomSheet, SemanticsBinding.ensureSemantics, custom FlutterViewController subclasses, and various plugins. The reproduction requires the combination of the Router API and DropdownMenu/MenuAnchor — neither alone is sufficient.

Relationship to #186582 / #187167

This produces the same end state as #186582 (the iOS accessibility bridge is torn down), but I want to flag a distinction rather than assume it:

So this is filed as a distinct, minimal repro with a reliable trigger that the in-flight fix won't cover. If maintainers determine it's the same underlying cause as #186582, please treat this as that issue's iOS-Router reproduction (and an indication that #187167's scope may need to expand).

Workaround

Replacing the DropdownMenu with a showModalBottomSheet list picker keeps the accessibility tree intact under the same test.

Note for anyone reproducing app-side

You can't observe this from app code by reading view.accessibilityElements: without an attached assistive-technology consumer, iOS only exposes a shallow placeholder (count ~2) and materializes the full tree lazily for VoiceOver / Accessibility Inspector / XCUITest. Observe the tree with the Accessibility Inspector or an XCUITest assertion, not in-app element counting.

Expected results

Selecting a dropdown entry updates the selection and leaves the accessibility tree
intact — exactly what happens when useGoRouter = false (plain MaterialApp).

Actual results

With useGoRouter = true, selecting any entry wipes the entire iOS accessibility
tree and it is never rebuilt. This breaks VoiceOver and any UIKit-level automation
(XCUITest, Accessibility Inspector, etc.).

Code sample

Code sample

Requires go_router as a dependency. This is available as a repro project here: https://github.com/elitree/dropdown_gorouter_repro

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

/// true  -> MaterialApp.router + go_router  (a11y tree COLLAPSES after a selection)
/// false -> plain MaterialApp              (tree survives)
const bool useGoRouter = true;

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

final _router = GoRouter(
  routes: [GoRoute(path: '/', builder: (context, state) => const DropdownPage())],
);

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    if (useGoRouter) {
      return MaterialApp.router(title: 'repro', routerConfig: _router);
    }
    return const MaterialApp(title: 'repro', home: DropdownPage());
  }
}

class DropdownPage extends StatefulWidget {
  const DropdownPage({super.key});
  @override
  State<DropdownPage> createState() => _DropdownPageState();
}

class _DropdownPageState extends State<DropdownPage> {
  String _selected = 'Owner';
  static const _entries = <String>['Owner', 'Owner Last', 'Parcel ID', 'None'];
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('repro')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text('MARKER ELEMENT ONE'),
            const SizedBox(height: 24),
            ElevatedButton(onPressed: () {}, child: const Text('MARKER BUTTON TWO')),
            const SizedBox(height: 48),
            DropdownMenu<String>(
              requestFocusOnTap: false,
              initialSelection: _selected,
              onSelected: (v) { if (v != null) setState(() => _selected = v); },
              dropdownMenuEntries: _entries
                  .map((e) => DropdownMenuEntry<String>(value: e, label: e))
                  .toList(),
            ),
            const SizedBox(height: 24),
            Text('Selected: $_selected'),
          ],
        ),
      ),
    );
  }
}

Screenshots or Video

Screenshots / Video demonstration
dropdown_bug.mp4

Logs

Logs
fvm flutter run -d 3B4AC0E0-9B84-47D2-969B-0F010184BF4E
Resolving dependencies... 
Downloading packages... 
  matcher 0.12.19 (0.12.20 available)
  meta 1.17.0 (1.18.3 available)
  test_api 0.7.10 (0.7.12 available)
  vector_math 2.2.0 (2.4.0 available)
Got dependencies!
4 packages have newer versions incompatible with dependency constraints.
Try `flutter pub outdated` for more information.
Launching lib/main.dart on iPhone 16e in debug mode...
Running Xcode build...                                                  
Xcode build done.                                           13.0s
Syncing files to device iPhone 16e...                               35ms

Flutter run key commands.
r Hot reload. 🔥🔥🔥
R Hot restart.
h List all available interactive commands.
d Detach (terminate "flutter run" but leave application running).
c Clear the screen
q Quit (terminate the application on the device).

A Dart VM Service on iPhone 16e is available at: http://127.0.0.1:51576/Lt6rZAFG35A=/
The Flutter DevTools debugger and profiler on iPhone 16e is available at:
http://127.0.0.1:51576/Lt6rZAFG35A=/devtools/?uri=ws://127.0.0.1:51576/Lt6rZAFG35A=/ws

Application finished.

Flutter Doctor output

Doctor output
fvm flutter doctor -v
[✓] Flutter (Channel stable, 3.41.9, on macOS 26.5.1 25F80 darwin-arm64, locale en-US) [392ms]
    • Flutter version 3.41.9 on channel stable at /Users/eligeller/fvm/versions/3.41.9
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 00b0c91f06 (5 weeks ago), 2026-04-29 10:03:19 -0700
    • Engine revision 42d3d75a56
    • Dart version 3.11.5
    • DevTools version 2.54.2
    • Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios,
      cli-animations, enable-native-assets, 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) [1,752ms]
    • Android SDK at /Users/eligeller/Library/Android/sdk
    • Emulator version 36.5.10.0 (build_id 15081367) (CL:N/A)
    • Platform android-37.0, build-tools 36.1.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 21.0.10+-117844308-b1163.108)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 26.3) [981ms]
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 17C519
    • CocoaPods version 1.16.2

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

[✓] Connected device (6 available) [6.1s]
    • Eli iPhone 16 Pro (wireless) (mobile)  • 00008140-000603510193001C            • ios            • iOS 26.5 23F77
    • Eli iPhone 11 (wireless) (mobile)      • 00008030-000E10513A38802E            • ios            • iOS 26.5 23F77
    • Ashley’s iPhone 17 (wireless) (mobile) • 00008150-001571412186401C            • ios            • iOS 26.5.1 23F81
    • iPhone 16e (mobile)                    • 3B4AC0E0-9B84-47D2-969B-0F010184BF4E • ios            •
      com.apple.CoreSimulator.SimRuntime.iOS-26-2 (simulator)
    • macOS (desktop)                        • macos                                • darwin-arm64   • macOS 26.5.1 25F80
      darwin-arm64
    • Chrome (web)                           • chrome                               • web-javascript • Google Chrome
      148.0.7778.216
    ! Error: Browsing on the local area network for Eli’s iPad Pro. 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 [302ms]
    • All expected network resources are available.

• No issues found!

Activity

  1. changed the title [-]DropdownMenu selection tears down the entire iOS accessibility tree when the app uses the Router API (go_router / MaterialApp.router)[/-] [+][iOS] DropdownMenu selection tears down the entire iOS accessibility tree when the app uses the Router API (go_router / MaterialApp.router)[/+] on Jun 5, 2026
  2. added
    in triagePresently being triaged by the triage team
    platform-iosiOS applications specifically
    engineflutter/engine related. See also e: labels.
    has reproducible stepsThe issue has been confirmed reproducible and is ready to work on
    fyi-iosFor the attention of iOS platform team
    team-accessibilityOwned by Framework Accessibility team (i.e. responsible for accessibility code in flutter/flutter)
    a: accessibilityAccessibility, e.g. VoiceOver or TalkBack. (aka a11y)
    team-iosOwned by iOS platform team
    and removed
    in triagePresently being triaged by the triage team
    fyi-iosFor the attention of iOS platform team
    team-accessibilityOwned by Framework Accessibility team (i.e. responsible for accessibility code in flutter/flutter)
    on Jun 5, 2026
  3. mbcorona commented on Jun 5, 2026

    @mbcorona
    Member

    Thanks for the isolation here and for digging into why #187167 won't cover this one.

    Sending to the iOS team to match #186582 — they decided that whole accessibility-bridge teardown problem lives in the iOS embedding side rather than framework accessibility, so this fits there too.

    I'll leave it open instead of closing it as a duplicate. You've shown the VC-reattach path that #187167 fixes doesn't even fire in your case, so this is worth tracking as its own repro.
    Linking #186582 and #187167 for context. Thanks again!

  4. added a commit that references this issue on Jun 5, 2026
  5. LouiseHsu commented on Jun 11, 2026

    @LouiseHsu
    Contributor

    @chunhtai Do you have any insights into this?

  6. LongCatIsLooong commented on Jun 11, 2026

    @LongCatIsLooong
    Contributor

    Potentially related: #187198

  7. flutter-triage-bot commented on Jul 1, 2026

    @flutter-triage-bot

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

  8. hellohuanlin commented on Jul 9, 2026

    @hellohuanlin
    Contributor

    @QuncCccccc we see your PR - are you working on this? can we assign it to you?

  9. self-assigned this
    on Jul 9, 2026
  10. QuncCccccc commented on Jul 9, 2026

    @QuncCccccc
    Contributor

    Sure. I assigned myself.

  11. added
    P2Important issues not at the top of the work list
    triaged-iosTriaged by iOS platform team
    on Jul 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

P2Important issues not at the top of the work lista: accessibilityAccessibility, e.g. VoiceOver or TalkBack. (aka a11y)engineflutter/engine related. See also e: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onplatform-iosiOS applications specificallyteam-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