Repository navigation
Description
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
- Run on an iOS simulator or device (
flutter run) withuseGoRouter = true. - Open Xcode → Open Developer Tool → Accessibility Inspector and target the simulator/device.
- Inspect the page — the marker
Text, the button, and the dropdown are all present in the accessibility hierarchy. - Tap the
DropdownMenuand select any entry. - Re-inspect: the accessibility tree is now empty — the marker
Textand 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:
- It is not addressed by [iOS] Rebind accessibility bridge after view controller changes #187167. That PR fixes the bridge teardown that happens through a new
FlutterViewControllerreattach. I instrumented the VC lifecycle during a reproduced collapse and saw zero lifecycle transitions and a single, constant owner-VC instance — the reattach path the PR patches never fires in this scenario. - It may still share a root cause with [iOS] Accessibility tree is lost after reusing a FlutterEngine with a new FlutterViewController #186582. I could not distinguish, with app/VC-level instrumentation alone, between
SetOwnerViewController(self)being re-invoked with the same instance (which still runsaccessibility_bridge_.reset()) and a genuinely separate reset path. Confirming that would need engine-level logging inplatform_view_ios.mm.
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
[-]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)[/+]mbcorona commentedon Jun 5, 2026
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!
Note upstream issue flutter/flutter#187611 in README
LouiseHsu commentedon Jun 11, 2026
@chunhtai Do you have any insights into this?
LongCatIsLooong commentedon Jun 11, 2026
Potentially related: #187198
flutter-triage-bot commentedon Jul 1, 2026
The
triaged-accessibilitylabel is irrelevant if there is noteam-accessibilitylabel orfyi-accessibilitylabel.hellohuanlin commentedon Jul 9, 2026
@QuncCccccc we see your PR - are you working on this? can we assign it to you?
QuncCccccc commentedon Jul 9, 2026
Sure. I assigned myself.