{"record":{"id":"e81c3628b3e688e3","repo":"wezterm/wezterm","slug":"invalid-m-escape","errorCode":null,"errorMessage":"invalid \\\\M escape: {}","messagePattern":"invalid \\\\\\\\M escape: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"wezterm-escape-parser/src/tmux_cc/mod.rs","lineNumber":622,"sourceCode":"                    }\n                    b'$' => {\n                        // Hidden marker\n                        *state = State::Ground;\n                    }\n                    _ => {\n                        // Invalid syntax\n                        bail!(\"Invalid \\\\ escape: {}\", b);\n                    }\n                }\n            }\n\n            State::Meta => {\n                if b == b'-' {\n                    *state = State::Meta1;\n                } else if b == b'^' {\n                    *state = State::Ctrl(0o200);\n                } else {\n                    bail!(\"invalid \\\\M escape: {}\", b);\n                }\n            }\n\n            State::Meta1 => {\n                result.push(b | 0o200);\n                *state = State::Ground;\n            }\n\n            State::Ctrl(c) => {\n                if b == b'?' {\n                    result.push(*c | 0o177);\n                } else {\n                    result.push((b & 0o37) | *c);\n                }\n                *state = State::Ground;\n            }\n\n            State::Octal2(prior) => {","sourceCodeStart":604,"sourceCodeEnd":640,"githubUrl":"https://github.com/wezterm/wezterm/blob/3ff7522b9617ec920f7fbdb22b57e93d42d93ee9/wezterm-escape-parser/src/tmux_cc/mod.rs#L604-L640","documentation":"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.","triggerScenarios":"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.","commonSituations":"Hand-crafted or replayed tmux control-mode test transcripts that use \\M incorrectly; tmux/wezterm version drift changing the accepted meta forms.","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"],"exampleFix":"// before: emitting an incomplete meta escape\noutput.push_str(\"\\\\Ma\");\n\n// after: meta-a is \\M-a (sets bit 0o200 on the following byte)\noutput.push_str(\"\\\\M-a\");","handlingStrategy":"try-catch","validationCode":"// \\M must be followed by '-' or '^', then one more byte\nfn meta_escapes_ok(bytes: &[u8]) -> bool {\n    let mut i = 0;\n    while i + 1 < bytes.len() {\n        if bytes[i] == b'\\\\' && bytes[i + 1] == b'M' {\n            match bytes.get(i + 2) {\n                Some(b'-') | Some(b'^') => i += 3, // \\M- or \\M^ plus payload byte\n                None => return true,              // may continue in next chunk\n                _ => return false,\n            }\n        } else {\n            i += 1;\n        }\n    }\n    true\n}","typeGuard":null,"tryCatchPattern":"match parser.advance_bytes(&chunk) {\n    Ok(events) => events_out.extend(events),\n    Err(err) if err.to_string().contains(\"\\\\M escape\") => {\n        log::warn!(\"skipping line with bad \\\\M escape: {err:#}\");\n    }\n    Err(err) => return Err(err),\n}","preventionTips":["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"],"tags":["tmux","escape-sequence","parser","rust","wezterm"],"backgroundTag":"invalid-escape-sequence","analyzedSha":"3ff7522b9617ec920f7fbdb22b57e93d42d93ee9","analyzedAt":"2026-08-20T04:47:31.434Z","contentChangedAt":"2026-08-20T04:47:31.434Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}