python/cpython · error · KeySpecError
\C- followed by invalid key
Error message
\C- followed by invalid key
What it means
KeySpecError from _parse_single_key_sequence in Lib/_pyrepl/keymap.py. After the Ctrl modifier \C- is accepted, the remaining spec must resolve to exactly a single character or the named keys 'left'/'right'. Any other base key (multi-char name like 'home', 'f1', 'up') after \C- cannot be turned into a control byte and raises this error.
Source
Thrown at Lib/_pyrepl/keymap.py:189
% (ret, s + 2, repr(key))
)
ret = _keynames[ret]
s = t + 1
else:
raise KeySpecError(
"unknown backslash escape %s at char %d of %s"
% (repr(c), s + 2, repr(key))
)
else:
ret = key[s]
s += 1
if ctrl:
if len(ret) == 1:
ret = chr(ord(ret) & 0x1F) # curses.ascii.ctrl()
elif ret in {"left", "right"}:
ret = f"ctrl {ret}"
else:
raise KeySpecError("\\C- followed by invalid key")
result = [ret], s
if meta:
result[0].insert(0, "\033")
return result
def compile_keymap(keymap, empty=b""):
r = {}
for key, value in keymap.items():
if isinstance(key, bytes):
first = key[:1]
else:
first = key[0]
r.setdefault(first, {})[key[1:]] = value
for key, value in r.items():
if empty in value:
if len(value) != 1:View on GitHub (pinned to bc6749cc3b)
Solutions
- Bind such keys without the Ctrl modifier: \<home>, \<f1> are addressable directly.
- For ctrl+arrow-style sequences, terminals send escape-prefixed codes — use the raw escape sequence (often \M- or the literal bytes your terminal emits, discoverable with read -r in a shell) instead of \C-.
- Restrict \C- to letters/digits/punctuation (single chars) and left/right only.
Example fix
# before
keymap = {r'\C-<home>': 'beginning-of-line'}
# after
keymap = {r'\<home>': 'beginning-of-line'} Defensive patterns
Strategy: validation
Validate before calling
import re
def ctrl_target_valid(spec):
# after removing \C- and \M-, the rest must be a single char or left/right
body = re.sub(r'\\[cCmM]-', '', spec).strip('\\<>')
return len(body) == 1 or body.lower() in {'left', 'right'} Prevention
- Use \C- only with single characters, or left/right.
- Bind function/special keys without Ctrl: \<f1>, \<home>.
- Learn what your terminal actually sends (cat -v) and bind that sequence.
When it happens
Trigger: Specs like "\\C-<f1>" or "\\C-up" — i.e. \C- combined with any key that is not a single character and not left/right. The final block checks len(ret) == 1 or membership in {'left','right'} and otherwise raises.
Common situations: Trying to bind chord-style shortcuts to function keys (\C-<home>); assuming terminals transmit 'ctrl + arrow' as a single control byte; translated keymaps from GUI editors that freely combine Ctrl with any key.
Related errors
- \C must be followed by `-' (char %d of %s)
- doubled \C- (char %d of %s)
- \M must be followed by `-' (char %d of %s)
- doubled \M- (char %d of %s)
- unterminated \< starting at char %d of %s
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/efca4cd4051d0b79.
Report an issue: GitHub.