Repository navigation
Description
Reproduced on Flutter 3.47.4 stable (9584c67), Chrome on macOS. The code involved is unchanged on master 697012a (links below).
On the web, a semantics text field's <input> stays empty until the field has been focused once. Assistive technology reads the DOM element, so a screen reader browsing a form reads every filled field as empty until the user enters each one. The framework side is correct: the semantics tree already carries each field's value.
Steps to reproduce
- Run the code sample below on the web (
flutter run -d chrome, or build for web and serve it). - Turn semantics on, either with a screen reader or by activating the placeholder from the DevTools console:
document.querySelector('flt-semantics-placeholder').click()
- Without focusing either field, read the
<input>values, for example withand read the accessibility tree (the DevTools Accessibility pane, or CDP[...document.querySelectorAll('input')].map((i) => `${i.getAttribute('aria-label')}=${JSON.stringify(i.value)}`).join(' ')
Accessibility.getFullAXTree). - Click Load, then Reps, and read them again.
The Save button is in the sample only so that the route's default focus does not land on the first field. If it did, that field would be activated and would hide the bug for that field.
Expected results
Before any focus, Load reads value "100" and Reps reads "5". The semantics tree already carries those values. A widget test on the same sample gives:
Load: value="100"
Reps: value="5"
Widget test that prints the semantics values
import 'package:flutter_test/flutter_test.dart';
import 'package:repro/main.dart' as field; // the code sample below
void main() {
testWidgets('field value', (tester) async {
final h = tester.ensureSemantics();
field.main();
await tester.pump();
for (final l in ['Load', 'Reps']) {
final d = find.semantics.byLabel(l).evaluate().single.getSemanticsData();
debugPrint('$l: value="${d.value}"');
}
h.dispose();
});
}Actual results
Both <input> elements are empty, and the accessibility tree has no value for either text box. Each field gets its value only once it has been focused, and keeps it afterwards. This happens with any number of fields, for example a grid of inputs in a real app.
Code sample
Code sample
import 'package:flutter/material.dart';
void main() => runApp(
MaterialApp(
home: Scaffold(
body: Column(
children: [
TextButton(onPressed: () {}, child: const Text('Save')), // takes the route's default focus
TextField(controller: TextEditingController(text: '100'), decoration: const InputDecoration(labelText: 'Load')),
TextField(controller: TextEditingController(text: '5'), decoration: const InputDecoration(labelText: 'Reps')),
],
),
),
),
);Screenshots or Video
Not applicable: the logs below are the evidence.
Logs
Logs
Chrome, semantics on. DOM is each <input>'s value by its aria-label; AX is the accessibility tree without generic and static-text nodes.
unfocused DOM Load="" Reps="" | AX [ 'button "Save" focused=true', 'textbox "Load"', 'textbox "Reps"' ]
after Load DOM Load="100" Reps=""
after Reps DOM Load="100" Reps="5" | AX [
'button "Save"',
'textbox "Load" value="100"',
'textbox "Reps" value="5" focused=true'
]
Cause
SemanticTextField never mirrors semanticsObject.value onto its editableElement.
SemanticTextField.update()writes the size,aria-label,aria-required,aria-description, the disabled state and the input type, but neversemanticsObject.value.- The value reaches
editableElementonly afterSemanticsTextEditingStrategy.activate()has attached it, andactivate()runs only when the node has focus (update(), thehasFocusbranch). The text-editing channel then writes the editing state;DefaultTextEditingStrategy.setEditingStatereturns early while the strategy is not enabled. After that, the element keeps the last value it had.
This is unchanged on master: SemanticTextField.update() at 697012a97f has no write of semanticsObject.value either.
Suggested fix
In SemanticTextField.update(), when this field is not SemanticsTextEditingStrategy._instance?.activeTextField and semanticsObject.isValueDirty, set editableElement.value = semanticsObject.value ?? ''. Skip this for obscured fields, or write a masked value. Leave the active field alone, so that the editing channel stays the source of truth while the user is typing. This also narrows the window in #194186.
Related issues
- [web][a11y] Semantic text field erases input typed between browser focus and SemanticsTextEditingStrategy.activate() #194186 (open), "[web][a11y] Semantic text field erases input typed between browser focus and SemanticsTextEditingStrategy.activate()". It sits at the same boundary, because the
<input>only gets its value insideactivate().
I searched for SemanticTextField value, SemanticsTextEditingStrategy, semantics TextField value web empty, web semantics input value unfocused, web a11y textfield value screen reader, TextField value VoiceOver web and screen reader input value empty web flutter, and found no other match.
Flutter Doctor output
Doctor output
[✓] Flutter (Channel stable, 3.47.4, on macOS 27.0.1 26A434 darwin-arm64, locale en-GB)
• Flutter version 3.47.4 on channel stable at ~/Development/flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 9584c6713b (5 weeks ago), 2026-09-10 15:25:10 -0700
• Engine revision 06a2e2a110
• Dart version 3.13.3
• 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
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Connected device (2 available)
• macOS (desktop) • macos • darwin-arm64 • macOS 27.0.1 26A434 darwin-arm64
• Chrome (web) • chrome • web-javascript • Google Chrome 155.0.8059.82
[✓] Network resources
• All expected network resources are available.
(Android and Xcode checks timed out on this machine and are left out; they do not apply to these web/framework reports.)
Activity
suryaKommana2662 commentedon Oct 19, 2026
@jorgelrj Thanks for the report. I reproduced this issue on Flutter Web in Chrome. The input values become available in the HTML elements only after the respective fields receive focus. routing to the
team-accessibilityfor further investigation I observed the following results:Command used:
Observations:
Flutter Doctor Output
flutter-zl commentedon Oct 21, 2026
flutter-demo-apps/working on/issue_194547_before/. Semantics is on at startup.[...document.querySelectorAll('flt-semantics input')].map((i) => i.value)in the console. Then click the first field and run it again.["", ""]before any click,["first field", ""]after focusing the first. Fixed:["first field", "second field"]from the start.