{"record":{"id":"efca4cd4051d0b79","repo":"python/cpython","slug":"c-followed-by-invalid-key","errorCode":null,"errorMessage":"\\C- followed by invalid key","messagePattern":"\\\\C- followed by invalid key","errorType":"validation","errorClass":"KeySpecError","httpStatus":null,"severity":"error","filePath":"Lib/_pyrepl/keymap.py","lineNumber":189,"sourceCode":"                        % (ret, s + 2, repr(key))\n                    )\n                ret = _keynames[ret]\n                s = t + 1\n            else:\n                raise KeySpecError(\n                    \"unknown backslash escape %s at char %d of %s\"\n                    % (repr(c), s + 2, repr(key))\n                )\n        else:\n            ret = key[s]\n            s += 1\n    if ctrl:\n        if len(ret) == 1:\n            ret = chr(ord(ret) & 0x1F)  # curses.ascii.ctrl()\n        elif ret in {\"left\", \"right\"}:\n            ret = f\"ctrl {ret}\"\n        else:\n            raise KeySpecError(\"\\\\C- followed by invalid key\")\n\n    result = [ret], s\n    if meta:\n        result[0].insert(0, \"\\033\")\n    return result\n\n\ndef compile_keymap(keymap, empty=b\"\"):\n    r = {}\n    for key, value in keymap.items():\n        if isinstance(key, bytes):\n            first = key[:1]\n        else:\n            first = key[0]\n        r.setdefault(first, {})[key[1:]] = value\n    for key, value in r.items():\n        if empty in value:\n            if len(value) != 1:","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pyrepl/keymap.py#L171-L207","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\nkeymap = {r'\\C-<home>': 'beginning-of-line'}\n\n# after\nkeymap = {r'\\<home>': 'beginning-of-line'}","handlingStrategy":"validation","validationCode":"import re\n\ndef ctrl_target_valid(spec):\n    # after removing \\C- and \\M-, the rest must be a single char or left/right\n    body = re.sub(r'\\\\[cCmM]-', '', spec).strip('\\\\<>')\n    return len(body) == 1 or body.lower() in {'left', 'right'}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["python","pyrepl","keymap","ctrl-key","parsing"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}