python/cpython · error · KeySpecError
unknown backslash escape %s at char %d of %s
Error message
unknown backslash escape %s at char %d of %s
What it means
KeySpecError from _parse_single_key_sequence in Lib/_pyrepl/keymap.py. After a backslash, the next character must be one of the recognized escapes: _escapes entries, 'c' (\C-), 'm' (\M-), octal digits, 'x' (hex), or '<' (named key). Anything else is an unknown backslash escape and raises this error showing the offending character.
Source
Thrown at Lib/_pyrepl/keymap.py:176
ret = chr(int(n, 16))
s += 4
elif c == "<":
t = key.find(">", s)
if t == -1:
raise KeySpecError(
"unterminated \\< starting at char %d of %s"
% (s + 1, repr(key))
)
ret = key[s + 2 : t].lower()
if ret not in _keynames:
raise KeySpecError(
"unrecognised keyname `%s' at char %d of %s"
% (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 resultView on GitHub (pinned to bc6749cc3b)
Solutions
- Check the _escapes dict at the top of Lib/_pyrepl/keymap.py and use only its escape letters.
- For control/meta use \C- and \M-; for named keys use \<name>; for arbitrary chars use octal (\NNN) or hex (\xNN) forms.
- Strip/escape stray backslashes from dynamically built spec strings before parsing.
Example fix
# before
keymap = {r'\z': 'foo'}
# after
# use hex escape for the literal char, e.g. Ctrl-Z is \C-z or \x1a
keymap = {r'\C-z': 'foo'} Defensive patterns
Strategy: validation
Validate before calling
from _pyrepl.keymap import _escapes, _keynames
def only_known_escapes(spec):
import re
for m in re.finditer(r'\\(.)', spec):
c = m.group(1).lower()
if c not in _escapes and c not in 'cmx<' and not c.isdigit():
return False
return True Prevention
- Restrict escapes to the module's _escapes table plus \C-, \M-, octal \NNN, hex \xNN, \<name>.
- Sanitize path-like strings before they reach key-spec code.
- Parse specs in tests to surface unknown escapes.
When it happens
Trigger: Specs containing an escape the parser does not know, e.g. "\\e" is fine (in _escapes) but "\\z", "\\t" only if 't' is in _escapes, or Windows-style "\\\\" handling mistakes; also single trailing backslash where key[s+1] indexing grabs a wrong char.
Common situations: Porting readline init syntax (which supports more escapes) into pyrepl keymaps; platform path-separator backslashes leaking into key specs; assuming \n/\r/\t spellings without checking _escapes in the module.
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/6c6e5ab8e4da15fe.
Report an issue: GitHub.