{"record":{"id":"c1002f55c25ec741","repo":"can1357/oh-my-pi","slug":"cannot-encode-ctrl-chord-character","errorCode":null,"errorMessage":"cannot encode ctrl chord ${character}","messagePattern":"cannot encode ctrl chord (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/tui/src/debug-server.ts","lineNumber":115,"sourceCode":"\nfunction modifiedSpecial(sequence: string, modifier: number): string {\n\tif (modifier === 1) return sequence;\n\tif (sequence === \"\\t\" && (modifier & 1) === 0) {\n\t\treturn modifier === 2 ? \"\\x1b[Z\" : `\\x1b[1;${modifier}Z`;\n\t}\n\tconst csiFinal = sequence.match(/^\\x1b\\[([ABCDHF])$/);\n\tif (csiFinal) return `\\x1b[1;${modifier}${csiFinal[1]}`;\n\tconst ss3Final = sequence.match(/^\\x1bO([PQRS])$/);\n\tif (ss3Final) return `\\x1b[1;${modifier}${ss3Final[1]}`;\n\tconst tilde = sequence.match(/^\\x1b\\[(\\d+)~$/);\n\tif (tilde) return `\\x1b[${tilde[1]};${modifier}~`;\n\treturn sequence;\n}\n\nfunction ctrlCharacter(character: string): string {\n\tconst code = character.toUpperCase().charCodeAt(0);\n\tif ((code >= 64 && code <= 95) || code === 63) return String.fromCharCode(code === 63 ? 127 : code & 31);\n\tthrow new Error(`cannot encode ctrl chord ${character}`);\n}\n\nfunction encodeChord(token: string): string {\n\tlet rest = token;\n\tlet ctrl = false;\n\tlet alt = false;\n\tlet shift = false;\n\tif (/^C-/i.test(rest)) {\n\t\tctrl = true;\n\t\trest = rest.slice(2);\n\t}\n\tif (/^(?:A|M)-/i.test(rest)) {\n\t\talt = true;\n\t\trest = rest.slice(2);\n\t}\n\tif (/^S-/i.test(rest)) {\n\t\tshift = true;\n\t\trest = rest.slice(2);","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/tui/src/debug-server.ts#L97-L133","documentation":"ctrlCharacter() encodes a Ctrl-chord for the TUI debug server's key-injection protocol. Ctrl only maps cleanly for characters whose code is 64–95 (or '?', which becomes DEL); other characters have no C0 control encoding, so it throws.","triggerScenarios":"Encoding a key token like \"C-x\" where x's uppercase char code is outside 64–95 and isn't '?' — e.g. C-1, C-/, C-space-as-letter, or any digit/symbol.","commonSituations":"Sending debug-server key sequences with ctrl modifiers on keys that terminals themselves cannot represent as ctrl chords (digits, punctuation); typo'd key tokens in test scripts.","solutions":["Use a ctrl chord only with letters (a–z) or '@', '[', '\\\\', ']', '^', '_', '?'","Remove the C- modifier from the token if the key can't be a ctrl chord","Use a special key name (from SPECIAL_KEYS) with the C- prefix if supported"],"exampleFix":"// before\nencodeChord(\"C-1\") // throws\n// after\nencodeChord(\"1\") // plain key, or a supported chord like \"C-a\"","handlingStrategy":"validation","validationCode":"function canEncodeCtrl(ch: string): boolean {\n  const code = ch.toUpperCase().charCodeAt(0);\n  return (code >= 64 && code <= 95) || code === 63;\n}","typeGuard":"function isCtrlEncodable(token: string): boolean {\n  const m = /^C-(.)$/i.exec(token);\n  return !m || canEncodeCtrl(m[1]);\n}","tryCatchPattern":"try {\n  seq = encodeChord(token);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith(\"cannot encode ctrl chord\")) {\n    logger.warn(\"dropping non-encodable ctrl chord\", { token });\n    continue;\n  }\n  throw err;\n}","preventionTips":["Only use C- with letters and the control-range punctuation (@, [, \\, ], ^, _, ?)","Don't synthesize ctrl chords for digits or other punctuation — terminals can't represent them","Validate tokens against a whitelist before building sequences"],"tags":["keyboard-input","encoding","debug"],"backgroundTag":"invalid-key-sequence","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}