Repository navigation
Description
Steps to reproduce
- Run a Flutter Web app with a
TextFieldon Chrome (macOS) - Switch to Korean IME and start typing (e.g., type "한")
- While the character is still composing (cursor is on the character, not yet committed), press Cmd+Tab to switch to another app
- Switch back to the Flutter Web app
- Press Backspace
Expected results
Backspace should delete the composed character normally.
Actual results
Backspace does not work. The following assertion error is thrown:
═══ EXCEPTION CAUGHT BY SERVICES LIBRARY ═══
Failed assertion: line 1155 pos 7: 'googValue.googcomposing.end <= googValue.text.length'
composingBase: 1, composingExtent: 2, text: 한
The composing range (1–2) exceeds text.length (1), causing an assertion failure. After this, Backspace and other key inputs stop working.
Root cause analysis
When the browser window loses focus (window.blur), a compositionend event fires. This removes the composing text from the DOM, but Flutter's internal composing range is not updated accordingly. This creates a mismatch in TextEditingValue:
text.length= 1 (the composed character was committed/shortened)composingBase= 1,composingExtent= 2 (still referencing the old composing range)
When the user returns and presses a key, TextEditingValue.fromJSON() hits the assertion before any app-level code can intercept.
Workarounds attempted (all failed)
| # | Approach | Result |
|---|---|---|
| 1 | addPostFrameCallback after _restoreFocus() to clear composing |
Too late, assertion already fired |
| 2 | AppLifecycleState.inactive to clear composing |
Web doesn't fire inactive (only hidden) |
| 3 | window.blur event listener via conditional import + composing cleanup |
No effect |
| 4 | activeElement.blur() to force IME commit + TextField key regeneration |
IME switches to English + still fails |
| 5 | Focus restore with 50ms delay + composing cleanup | No effect |
The core issue is that the assertion fires in the platform channel → TextEditingValue.fromJSON() path, before any app-level Dart code can intervene.
Key constraint
- English input: no issue
- Composing completed (cursor outside character): no issue
- Only occurs when composing is active (cursor on the character being composed)
Environment
- Flutter 3.10+ (stable)
- Chrome on macOS
- Korean IME (macOS default)
- Reproducible with both CanvasKit and HTML renderer
Related issues
- TextInputClient should receive correct composing range or ignore it on Flutter Web #65357 (composing range on web — fixed, but this edge case remains)
- [web] Assertion failure when inserting new lines #131023 (assertion failure with composing state — similar symptom, different trigger)
- [Flutter Web] When pressing the Tab key in TextField, incorrect behavior occurs while Japanese IME composition mode is ON. #147282 (Japanese IME + Tab key on web — similar pattern of IME composition + special key)
Activity
mbcorona commentedon Mar 5, 2026
Hi @tobedoit , Thanks for the report and root-cause analysis.
I was able to successfully reproduce this assertion failure using the following steps:
gks(forms "한") in theTextFieldwithout pressing Space/Enter (leave in composing state).Cmd+Tabto switch windows, thenCmd+Tabback to Chrome.Backspaceand the assertion fires.Triage Findings:
Routing to
team-webto investigate thecompositionendevent sync issue.[web] Drop stale composing range after text is replaced mid-compositi…
github-actions commentedon Oct 28, 2026
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 -vand a minimal reproduction of the issue.[web] Drop stale composing range after text is replaced mid-compositi…