After talking framework support into sending me a new input cover, the problem was not fixed, so I set an AI agent (claude) on to the task. Should have done that earlier: The report from claude is as follows:
The rapid duplicate letters come from the keyboard firmware, not from you. Your imprecise typing does play a part, but only as the trigger. That’s why the new input cover didn’t help.
What the log shows. I parsed all 4,125 reports in ~/chatter-detector.log (2026-07-07 to today). 2,878 of them have the same shape:
- First press held 15–25 ms. A normal tap of yours is 50–100 ms.
- Then a gap of 29–34 ms before the same key goes down again.
- The rate never changed: about 50 a day from July to today, with no drop after the cover swap.
Every gap lands on a ~3.3 ms grid, which is the keyboard controller’s scan clock. Only 3.6% of these happened while another key was held, so it isn’t from hitting two keys at once. The median time since your previous keystroke was 334 ms, so these are calm keystrokes, not fast mashing.
Why it happens. Framework’s own firmware source (FrameworkComputer/EmbeddedController, branch fwk-lilac-27116, keyboard_customization_13.c) sets two waiting times:
- after a key goes down, the controller ignores that key for 20 ms;
- after a key comes up, it ignores it for 30 ms.
These timings are reported the instant they’re seen and only blocked afterwards. Framework could switch on a stricter debounce mode that waits for the contact to settle first (CONFIG_KEYBOARD_STRICT_DEBOUNCE), but it doesn’t. So when the contact flickers open for a single scan during a press, this happens:
- At 20 ms the controller reports the key as released.
- It waits 30 ms.
- Your finger is still on the key, so it reports a new press.
One physical stroke becomes two characters. The 20 ms and 30 ms values match your two clusters exactly.
Where your typing comes in. Without per-key press counts this is only a rough comparison against normal letter frequency, but it’s clear:
- Frequent: stretch and bottom-row keys (V, G, B, C, M) and pinky/ring-finger keys (A, L, Backspace, Up).
- Rare: top-row keys you hit with a curled finger (E, R, T, O, I), even though E is the most common letter. T and R are wired on the same line as G, V and B, so it isn’t a bad circuit.
Hitting a key off-centre makes the contact flicker. Both covers behave the same because the cause is your finger angle combined with the firmware. The “fine while charging” pattern from your July forum post didn’t show up here: today you’ve been on AC all day and still got 41.
What you can do:
- Filter it in software (recommended). Have the detector grab the keyboard, hold back each key-release for about 36 ms, and drop a release followed by a re-press of the same key inside that window. That gives the strict behaviour Framework doesn’t ship. It’s safe because nobody can deliberately press the same key twice that fast; real repeats are at least ~60 ms apart. Key-presses get no extra delay, only releases do. I can build this into chatter-detector if you want.
- Ask Framework to enable the stricter debounce in the controller firmware. Add the evidence above to your forum thread ( Keyboard duplicate keys ).
- Type with more vertical strikes on the stretch and pinky keys. That reduces it but won’t fully stop it.
The findings are recorded in the cachyos skill under Keyboard double presses (commit 79ae5fd). The analysis scripts are in ~/claude-sysadm/tmp/.
result: Your duplicate keys come from the controller firmware: it reports changes instantly and only then waits 20/30 ms, so a contact flicker from off-centre hits types twice; a software filter in chatter-detector would fix it.
Sources:
- Framework forum: Keyboard duplicate keys (
- Framework forum: Keyboard adding extra keys
- Chromium EC keyboard_scan.c
- FrameworkComputer/EmbeddedController
I installed the fix that claude suggested (a rust binary he wrote earlier to analyse the keyboard output, now also filtering the duplicate events) and it works fine for me in my setup. I have seen multiple duplicate keys in the logs but they don’t make it into my writing any more.
The fix works for linux, probably needs a little configuration depending on flavor, because it filters the events into a virtual keyboard that then replaces your main keyboard.
If you want to try the fix, I am happy to share it.
According to these findings the problem is at its root a combination of my fat fingers and an insufficient debouncer in Framework BIOS firmware.
Cheers Thomas