can1357/oh-my-pi · error · Error
cannot encode ctrl chord ${character}
Error message
cannot encode ctrl chord ${character} What it means
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.
Source
Thrown at packages/tui/src/debug-server.ts:115
function modifiedSpecial(sequence: string, modifier: number): string {
if (modifier === 1) return sequence;
if (sequence === "\t" && (modifier & 1) === 0) {
return modifier === 2 ? "\x1b[Z" : `\x1b[1;${modifier}Z`;
}
const csiFinal = sequence.match(/^\x1b\[([ABCDHF])$/);
if (csiFinal) return `\x1b[1;${modifier}${csiFinal[1]}`;
const ss3Final = sequence.match(/^\x1bO([PQRS])$/);
if (ss3Final) return `\x1b[1;${modifier}${ss3Final[1]}`;
const tilde = sequence.match(/^\x1b\[(\d+)~$/);
if (tilde) return `\x1b[${tilde[1]};${modifier}~`;
return sequence;
}
function ctrlCharacter(character: string): string {
const code = character.toUpperCase().charCodeAt(0);
if ((code >= 64 && code <= 95) || code === 63) return String.fromCharCode(code === 63 ? 127 : code & 31);
throw new Error(`cannot encode ctrl chord ${character}`);
}
function encodeChord(token: string): string {
let rest = token;
let ctrl = false;
let alt = false;
let shift = false;
if (/^C-/i.test(rest)) {
ctrl = true;
rest = rest.slice(2);
}
if (/^(?:A|M)-/i.test(rest)) {
alt = true;
rest = rest.slice(2);
}
if (/^S-/i.test(rest)) {
shift = true;
rest = rest.slice(2);View on GitHub (pinned to 9690622007)
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
Example fix
// before
encodeChord("C-1") // throws
// after
encodeChord("1") // plain key, or a supported chord like "C-a" Defensive patterns
Strategy: validation
Validate before calling
function canEncodeCtrl(ch: string): boolean {
const code = ch.toUpperCase().charCodeAt(0);
return (code >= 64 && code <= 95) || code === 63;
} Type guard
function isCtrlEncodable(token: string): boolean {
const m = /^C-(.)$/i.exec(token);
return !m || canEncodeCtrl(m[1]);
} Try / catch
try {
seq = encodeChord(token);
} catch (err) {
if (err instanceof Error && err.message.startsWith("cannot encode ctrl chord")) {
logger.warn("dropping non-encodable ctrl chord", { token });
continue;
}
throw err;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- invalid key token ${token}
- unknown key ${rest}
- invalid utf-8 sequence
- invalid byte sequence: {:02x?}
- Invalid URL encoding in memory:// path: ${url.href}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/c1002f55c25ec741.
Report an issue: GitHub.