wezterm/wezterm · error
invalid \\M escape: {}
Error message
invalid \\M escape: {} What it means
Same tmux control-mode unvis decoder: after the two-byte intro \M the parser only accepts '-' (meta prefix, next byte OR 0o200) or '^' (meta-ctrl). Any other byte after \M raises this error because the meta escape cannot be completed.
Source
Thrown at wezterm-escape-parser/src/tmux_cc/mod.rs:622
}
b'$' => {
// Hidden marker
*state = State::Ground;
}
_ => {
// Invalid syntax
bail!("Invalid \\ escape: {}", b);
}
}
}
State::Meta => {
if b == b'-' {
*state = State::Meta1;
} else if b == b'^' {
*state = State::Ctrl(0o200);
} else {
bail!("invalid \\M escape: {}", b);
}
}
State::Meta1 => {
result.push(b | 0o200);
*state = State::Ground;
}
State::Ctrl(c) => {
if b == b'?' {
result.push(*c | 0o177);
} else {
result.push((b & 0o37) | *c);
}
*state = State::Ground;
}
State::Octal2(prior) => {View on GitHub (pinned to 3ff7522b96)
Solutions
- Fix the producer to emit the complete form \M-<byte> or \M^<byte>
- Upgrade wezterm if the tmux version in use added a new \M form
- When consuming untrusted/replayed streams, catch the error and skip the malformed line
Example fix
// before: emitting an incomplete meta escape
output.push_str("\\Ma");
// after: meta-a is \M-a (sets bit 0o200 on the following byte)
output.push_str("\\M-a"); Defensive patterns
Strategy: try-catch
Validate before calling
// \M must be followed by '-' or '^', then one more byte
fn meta_escapes_ok(bytes: &[u8]) -> bool {
let mut i = 0;
while i + 1 < bytes.len() {
if bytes[i] == b'\\' && bytes[i + 1] == b'M' {
match bytes.get(i + 2) {
Some(b'-') | Some(b'^') => i += 3, // \M- or \M^ plus payload byte
None => return true, // may continue in next chunk
_ => return false,
}
} else {
i += 1;
}
}
true
} Try / catch
match parser.advance_bytes(&chunk) {
Ok(events) => events_out.extend(events),
Err(err) if err.to_string().contains("\\M escape") => {
log::warn!("skipping line with bad \\M escape: {err:#}");
}
Err(err) => return Err(err),
} Prevention
- Emit complete meta escapes (\M-x / \M^x) from test fixtures and replay harnesses
- Never feed raw binary containing 0x5C bytes into the tmux control-mode parser
When it happens
Trigger: A parsed line containing \M followed by something other than '-' or '^' (e.g. \Mx), or a lone \M where the next byte is a newline or unrelated character; typically from a producer using a different meta-escape dialect or from unescaped binary in the stream.
Common situations: Hand-crafted or replayed tmux control-mode test transcripts that use \M incorrectly; tmux/wezterm version drift changing the accepted meta forms.
Related errors
AI-assisted analysis of wezterm/wezterm@3ff7522b96 (2026-08-20).
Data as JSON: /api/errors/e81c3628b3e688e3.
Report an issue: GitHub.