{"record":{"id":"0e0fc48df89f4e39","repo":"rust-lang/rust-analyzer","slug":"bad-spacing-other","errorCode":null,"errorMessage":"bad spacing {other}","messagePattern":"bad spacing (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/proc-macro-api/src/legacy_protocol/msg/flat.rs","lineNumber":427,"sourceCode":"    }\n    fn read_with_kind([id, text, kind, suffix]: [u32; 4]) -> LiteralRepr {\n        LiteralRepr { id: SpanId(id), text, kind: kind as u16, suffix }\n    }\n}\n\nimpl PunctRepr {\n    fn write(self) -> [u32; 3] {\n        let spacing = match self.spacing {\n            tt::Spacing::Alone | tt::Spacing::JointHidden => 0,\n            tt::Spacing::Joint => 1,\n        };\n        [self.id.0, self.char as u32, spacing]\n    }\n    fn read([id, char, spacing]: [u32; 3]) -> PunctRepr {\n        let spacing = match spacing {\n            0 => tt::Spacing::Alone,\n            1 => tt::Spacing::Joint,\n            other => panic!(\"bad spacing {other}\"),\n        };\n        PunctRepr { id: SpanId(id), char: char.try_into().unwrap(), spacing }\n    }\n}\n\nimpl IdentRepr {\n    fn write(self) -> [u32; 2] {\n        [self.id.0, self.text]\n    }\n    fn read(data: [u32; 2]) -> IdentRepr {\n        IdentRepr { id: SpanId(data[0]), text: data[1], is_raw: false }\n    }\n    fn write_with_rawness(self) -> [u32; 3] {\n        [self.id.0, self.text, self.is_raw as u32]\n    }\n    fn read_with_rawness([id, text, is_raw]: [u32; 3]) -> IdentRepr {\n        IdentRepr { id: SpanId(id), text, is_raw: is_raw == 1 }\n    }","sourceCodeStart":409,"sourceCodeEnd":445,"githubUrl":"https://github.com/rust-lang/rust-analyzer/blob/e8f7e90aa3e7b26aa9a000200f606c1078da99ec/crates/proc-macro-api/src/legacy_protocol/msg/flat.rs#L409-L445","documentation":"`PunctRepr::read` decodes punctuation spacing over the legacy proc-macro protocol: tag 0 maps to `tt::Spacing::Alone` and 1 to `tt::Spacing::Joint`. Any other value cannot be represented, so the decoder panics with `bad spacing {other}`.","triggerScenarios":"`PunctRepr::read` receives a spacing field other than 0 or 1 from the flat 3-word [id, char, spacing] representation.","commonSituations":"Mismatched proc-macro server/protocol versions where the spacing encoding changed; corrupted token buffers; a writer bug encoding spacing as a boolean-like value other than 0/1 (e.g. 2 for JointIsolated in other encodings).","solutions":["Align the proc-macro server version with rust-analyzer so both sides use the same spacing encoding","Fix the writer to emit only 0 (Alone) or 1 (Joint)","Validate spacing tags before decoding or upgrade off the legacy protocol"],"exampleFix":"// before\nlet spacing = 2; // invalid legacy encoding\n// after\nlet spacing = match punct.spacing {\n    tt::Spacing::Alone => 0,\n    tt::Spacing::Joint => 1,\n};","handlingStrategy":"validation","validationCode":"fn valid_spacing_tag(tag: u32) -> bool { tag <= 1 }","typeGuard":"fn is_known_spacing(tag: u32) -> bool {\n    matches!(tag, 0 | 1)\n}","tryCatchPattern":null,"preventionTips":["Encode spacing as exactly 0 (Alone) or 1 (Joint) on the write side","Keep protocol encodings synchronized between server and client","Check the 3-word [id, char, spacing] layout before decoding","Avoid carrying spacing values from other token encodings into the flat protocol"],"tags":["rust","proc-macro","protocol-decoding","panic"],"backgroundTag":"protocol-encoding-mismatch","analyzedSha":"e8f7e90aa3e7b26aa9a000200f606c1078da99ec","analyzedAt":"2026-09-03T21:08:06.959Z","contentChangedAt":"2026-09-03T21:08:06.959Z","schemaVersion":2},"datasetVersion":"2026-09-11T07:07:21.782Z"}