python/cpython · error · KeySpecError
\C must be followed by `-' (char %d of %s)
Error message
\C must be followed by `-' (char %d of %s)
What it means
KeySpecError from _parse_single_key_sequence in _pyrepl/keymap.py. When parsing a key specification string, the sequence \c must be followed by a literal '-' (i.e. \C-), because the parser only accepts Ctrl modifiers in the canonical \C-x form. Any other character after \c triggers this error with the 1-based offset into the spec.
Source
Thrown at Lib/_pyrepl/keymap.py:130
while s < len(keys):
k, s = _parse_single_key_sequence(keys, s)
r.extend(k)
return r
def _parse_single_key_sequence(key: str, s: int) -> tuple[list[str], int]:
ctrl = 0
meta = 0
ret = ""
while not ret and s < len(key):
if key[s] == "\\":
c = key[s + 1].lower()
if c in _escapes:
ret = _escapes[c]
s += 2
elif c == "c":
if key[s + 2] != "-":
raise KeySpecError(
"\\C must be followed by `-' (char %d of %s)"
% (s + 2, repr(key))
)
if ctrl:
raise KeySpecError(
"doubled \\C- (char %d of %s)" % (s + 1, repr(key))
)
ctrl = 1
s += 3
elif c == "m":
if key[s + 2] != "-":
raise KeySpecError(
"\\M must be followed by `-' (char %d of %s)"
% (s + 2, repr(key))
)
if meta:
raise KeySpecError(
"doubled \\M- (char %d of %s)" % (s + 1, repr(key))View on GitHub (pinned to bc6749cc3b)
Solutions
- Write the modifier with its dash: \C-x, not \cx or \C-x without the hyphen.
- For plain characters use the raw character or a named key like \<Ctrl-x>-style spelled forms the parser supports; check _keynames for recognized names.
- Validate custom key specs at startup by calling _pyrepl.keymap._parse_single_key_sequence on each so config typos fail loudly at load, not at keypress.
Example fix
# before
keymap = {r'\cx': 'cut'}
# after
keymap = {r'\C-x': 'cut'} Defensive patterns
Strategy: validation
Validate before calling
from _pyrepl.keymap import _parse_single_key_sequence
def valid_keyspec(spec):
try:
_parse_single_key_sequence(spec, 0)
return True
except Exception:
return False
assert valid_keyspec(r'\C-x'), 'spec must be \\C-<key> with dash' Try / catch
from _pyrepl.keymap import KeySpecError
try:
_parse_single_key_sequence(r'\cx', 0)
except KeySpecError as e:
print('bad key spec:', e) Prevention
- Always write modifiers as \C- and \M- with the hyphen.
- Compile/parse custom keymaps once at startup so typos fail fast with positions.
- Keep a lint step in tests: parse every key in your keymap dict.
When it happens
Trigger: Calling _parse_single_key_sequence (or compiling a keymap whose keys go through it) with a spec containing \c not followed by '-', e.g. "\\cX", "\\Cx", or "\\c[3~". Case is lowered, so both \C and \c are affected.
Common situations: Porting readline-style bindings like \C-x\C-c into pyrepl config and dropping the dash; copy-pasting key specs from readline docs (which accept ^X notation) into pyrepl keymaps; user keymaps in sitecustomize or REPL plugins.
Related errors
- 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
- unrecognised keyname `%s' at char %d of %s
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/f17b7d1304318c97.
Report an issue: GitHub.