bug(windows): VSCode can receive events out-of-order when an extension binds backspace key
- Dominant language
- Pascal
- Stars
- 534
- Forks
- 143
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 113
Description
Original report: https://community.software.sil.org/t/some-ipa-key-combinations-not-working-in-vs-code/10768
When any VSCode extension has a keybinding for the Bksp key, even if the extension does nothing but call `commands.executeCommand('deleteLeft')` (i.e. default behavior), the command may be executed out of order -- a subsequent keystroke received may be processed before the `deleteLeft` event. While the original reporter experienced this when using a Keyman keyboard, it is easily reproducible without Keyman being involved.
This is reliably reproducible on Windows. I have not tested on other platforms.
This appears to be a race condition between the system input queue and extension keybinding processing within VSCode. I don't know if there are ways to mitigate this within the extension itself -- I could not find any?
# Setup test
* clone [vscode-ext-backspace-bug repo](https://github.com/mcdurdin/vscode-ext-backspace-bug) and load it in VSCode
* `npm install`
* Press F5 to start a new VSCode instance with this extension loaded
# Testing with Keyman (reproducing original report)
* Install the [sil_ipa](https://keyman.com/keyboards/sil_ipa) keyboard in Keyman
* Switch to VSCode (extension running instance)
* Create a new file (Plain Text format is fine)
* Switch to the SIL IPA keyboard using the Windows Language Selector
* Type the key sequence p=. This should result in `ʘ`. Sometimes, you'll get the expected output, but other times, the `ʘ` will very briefly appear, and then be deleted, leaving `p`. (Background, Keyman will emit the `p` first, then delete it when = is pressed, and emit `ʘ`).
# Minimal repro without Keyman
To verify that Keyman is not involved in this, you can use the tiny sample 'emit' app, which simply generates a Bksp = ten times in a row using the Windows `SendInput` API. The output should be `==========`.
* Make sure that Keyman is _not_ running and that your default Windows keyboard is selected.
* Build and run src/emit/emit.vcxproj (or use src/emit/emit.exe)
* Make sure that the target application (i.e. VSCode with the extension running) is ready:
* Switch to VSCode
* Create a new file (Plain Text format is fine)
* Click on the emit window, and immediately click back into the VSCode edit window.
* After 3 seconds, emit will send the key events to VSCode.
The output should always be `==========`, but when the extension is active, you'll (probably) see `a=a=a=a=a=`. You can test this against VSCode without this extension running, or e.g. in Notepad.
The following [log](https://github.com/microsoft/vscode/wiki/Keybinding-Issues#basic-troubleshooting) shows the broken state (first 3 keystrokes only, a Bksp =):
```log
2025-10-09 13:05:01.615 [info] [Window] [KeybindingService]: / Soft dispatching keyboard event
2025-10-09 13:05:01.625 [info] [Window] [KeybindingService]: | Resolving A
2025-10-09 13:05:01.625 [info] [Window] [KeybindingService]: \ No keybinding entries.
2025-10-09 13:05:01.626 [info] [Window] [KeybindingService]: / Received keydown event - modifiers: [], code: KeyA, keyCode: 65, key: a
2025-10-09 13:05:01.626 [info] [Window] [KeybindingService]: | Converted keydown event - modifiers: [], code: KeyA, keyCode: 31 ('A')
2025-10-09 13:05:01.627 [info] [Window] [KeybindingService]: | Resolving A
2025-10-09 13:05:01.627 [info] [Window] [KeybindingService]: \ No keybinding entries.
2025-10-09 13:05:01.630 [info] [Window] [KeybindingService]: / Soft dispatching keyboard event
2025-10-09 13:05:01.634 [info] [Window] [KeybindingService]: | Resolving Backspace
2025-10-09 13:05:01.635 [info] [Window] [KeybindingService]: \ From 3 keybinding entries, matched markdown.extension.onBackspaceKey, when: editorTextFocus && !editorReadonly, source: user extension mcdurdin.markdown-keyman-backspace-bug.
2025-10-09 13:05:01.637 [info] [Window] [KeybindingService]: / Received keydown event - modifiers: [], code: Backspace, keyCode: 8, key: Backspace
2025-10-09 13:05:01.637 [info] [Window] [KeybindingService]: | Converted keydown event - modifiers: [], code: Backspace, keyCode: 1 ('Backspace')
2025-10-09 13:05:01.637 [info] [Window] [KeybindingService]: | Resolving Backspace
2025-10-09 13:05:01.637 [info] [Window] [KeybindingService]: \ From 3 keybinding entries, matched markdown.extension.onBackspaceKey, when: editorTextFocus && !editorReadonly, source: user extension mcdurdin.markdown-keyman-backspace-bug.
2025-10-09 13:05:01.639 [info] [Window] [KeybindingService]: + Invoking command markdown.extension.onBackspaceKey.
2025-10-09 13:05:01.639 [info] [Window] [KeybindingService]: / Soft dispatching keyboard event
2025-10-09 13:05:01.639 [info] [Window] [KeybindingService]: | Resolving =
2025-10-09 13:05:01.640 [info] [Window] [KeybindingService]: \ No keybinding entries.
2025-10-09 13:05:01.640 [info] [Window] [KeybindingService]: / Received keydown event - modifiers: [], code: Equal, keyCode: 187, key: =
2025-10-09 13:05:01.640 [info] [Window] [KeybindingService]: | Converted keydown event - modifiers: [], code: Equal, keyCode: 86 ('=')
2025-10-09 13:05:01.641 [info] [Window] [KeybindingService]: | Resolving =
2025-10-09 13:05:01.642 [info] [Window] [KeybindingService]: \ No keybinding entries.
2025-10-09 13:05:01.659 [info] [Window] [KeybindingService]: / Soft dispatching keyboard event
2025-10-09 13:05:01.659 [info] [Window] [KeybindingService]: | Resolving A
2025-10-09 13:05:01.660 [info] [Window] [KeybindingService]: \ No keybinding entries.
2025-10-09 13:05:01.660 [info] [Window] [KeybindingService]: / Received keydown event - modifiers: [], code: KeyA, keyCode: 65, key: a
2025-10-09 13:05:01.660 [info] [Window] [KeybindingService]: | Converted keydown event - modifiers: [], code: KeyA, keyCode: 31 ('A')
2025-10-09 13:05:01.660 [info] [Window] [KeybindingService]: | Resolving A
2025-10-09 13:05:01.660 [info] [Window] [KeybindingService]: \ No keybinding entries.
2025-10-09 13:05:01.665 [info] [Window] [KeybindingService]: / Soft dispatching keyboard event
2025-10-09 13:05:01.666 [info] [Window] [KeybindingService]: | Resolving Backspace
2025-10-09 13:05:01.666 [info] [Window] [KeybindingService]: \ From 3 keybinding entries, matched markdown.extension.onBackspaceKey, when: editorTextFocus && !editorReadonly, source: user extension mcdurdin.markdown-keyman-backspace-bug.
2025-10-09 13:05:01.666 [info] [Window] [KeybindingService]: / Received keydown event - modifiers: [], code: Backspace, keyCode: 8, key: Backspace
2025-10-09 13:05:01.666 [info] [Window] [KeybindingService]: | Converted keydown event - modifiers: [], code: Backspace, keyCode: 1 ('Backspace')
2025-10-09 13:05:01.666 [info] [Window] [KeybindingService]: | Resolving Backspace
2025-10-09 13:05:01.666 [info] [Window] [KeybindingService]: \ From 3 keybinding entries, matched markdown.extension.onBackspaceKey, when: editorTextFocus && !editorReadonly, source: user extension mcdurdin.markdown-keyman-backspace-bug.
2025-10-09 13:05:01.666 [info] [Window] [KeybindingService]: + Invoking command markdown.extension.onBackspaceKey.
2025-10-09 13:05:01.667 [info] [Window] [KeybindingService]: / Soft dispatching keyboard event
2025-10-09 13:05:01.667 [info] [Window] [KeybindingService]: | Resolving =
2025-10-09 13:05:01.667 [info] [Window] [KeybindingService]: \ No keybinding entries.
2025-10-09 13:05:01.667 [info] [Window] [KeybindingService]: / Received keydown event - modifiers: [], code: Equal, keyCode: 187, key: =
2025-10-09 13:05:01.667 [info] [Window] [KeybindingService]: | Converted keydown event - modifiers: [], code: Equal, keyCode: 86 ('=')
2025-10-09 13:05:01.667 [info] [Window] [KeybindingService]: | Resolving =
2025-10-09 13:05:01.667 [info] [Window] [KeybindingService]: \ No keybinding entries.
```
# References
* https://vscode-docs.readthedocs.io/en/stable/customization/keybindings/
* https://github.com/microsoft/vscode/wiki/Keybinding-Issues
* https://github.com/microsoft/vscode/issues/270731
*
# Potentially related bug reports
* https://github.com/Microsoft/vscode/issues/76488
* https://github.com/microsoft/vscode/issues/71238
* https://github.com/Microsoft/vscode/issues/4955
# Screencaps
## Incorrect output, when extension is active in VSCode
https://github.com/user-attachments/assets/110bb50c-d75a-4d82-b44a-b3e601e18262
## Correct output, when extension is inactive in VSCode
https://github.com/user-attachments/assets/981a14f1-93ca-485b-aa55-987147270cf7
## Correct output, in Notepad
https://github.com/user-attachments/assets/fe26f46c-857b-4c43-bff6-318c4ebae405
Contributor guide
Assessment
This issue has not been assessed yet.