python/cpython · error · KeySpecError
doubled \M- (char %d of %s)
Error message
doubled \M- (char %d of %s)
What it means
KeySpecError from _parse_single_key_sequence in Lib/_pyrepl/keymap.py. The Meta modifier can appear at most once per key spec; a second \M- while the parser is still looking for the base key raises 'doubled \M-' with the position of the offending token.
Source
Thrown at Lib/_pyrepl/keymap.py:147
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))
)
meta = 1
s += 3
elif c.isdigit():
n = key[s + 1 : s + 4]
ret = chr(int(n, 8))
s += 4
elif c == "x":
n = key[s + 2 : s + 4]
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))View on GitHub (pinned to bc6749cc3b)
Solutions
- Drop the duplicate: \M-\M-a -> \M-a.
- For a Ctrl+Meta chord use \C-\M-a or \M-\C-a (one of each modifier), never two \M-.
- Validate specs at config load with _parse_single_key_sequence.
Example fix
# before
keymap = {r'\M-\M-a': 'accept-line'}
# after
keymap = {r'\M-a': 'accept-line'}
# or a real chord: r'\C-\M-a' Defensive patterns
Strategy: validation
Validate before calling
import re
def no_doubled_meta(spec):
return len(re.findall(r'\\[mM]-', spec)) <= 1 Prevention
- At most one \M- per spec; combine modifiers as \C-\M-x instead.
- Lint merged keymap entries for repeated modifier tokens.
- Parse each spec via _parse_single_key_sequence in CI.
When it happens
Trigger: Key specs like "\\M-\\M-a" where \M- appears twice before a base character/key is produced. Single legitimate use such as \M-\C-a is fine because each modifier is tracked separately; only duplicate \M- tokens trip this.
Common situations: Double-prefixed Emacs-style bindings copied verbatim; macros or recorded sequences that emit two ESC prefixes; hand-merged keymap entries where a prefix was appended twice.
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)
- 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/19f85e4d6d1bdde5.
Report an issue: GitHub.