{"record":{"id":"6c08ef50090ad8da","repo":"GitoxideLabs/gitoxide","slug":"valid-macro-names-are-always-utf8-and-this-was-ver","errorCode":null,"errorMessage":"valid macro names are always UTF8 and this was verified","messagePattern":"valid macro names are always UTF8 and this was verified","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gix-attributes/src/search/outcome.rs","lineNumber":276,"sourceCode":"    }\n}\n\n/// Mutation\nimpl MetadataCollection {\n    /// Assign order ids to each attribute either in macros (along with macros themselves) or attributes of patterns, and store\n    /// them in this collection.\n    ///\n    /// Must be called before querying matches.\n    pub fn update_from_list(&mut self, list: &mut gix_glob::search::pattern::List<Attributes>) {\n        for pattern in &mut list.patterns {\n            match &mut pattern.value {\n                Value::MacroAssignments { id: order, assignments } => {\n                    *order = self.id_for_macro(\n                        pattern\n                            .pattern\n                            .text\n                            .to_str()\n                            .expect(\"valid macro names are always UTF8 and this was verified\"),\n                        assignments,\n                    );\n                }\n                Value::Assignments(assignments) => {\n                    self.assign_order_to_attributes(assignments);\n                }\n            }\n        }\n    }\n}\n\n/// Access\nimpl MetadataCollection {\n    /// Return an iterator over the contents of the map in an easy-to-consume form.\n    pub fn iter(&self) -> impl Iterator<Item = (&str, &Metadata)> {\n        self.name_to_meta.iter().map(|(k, v)| (k.as_str(), v))\n    }\n}","sourceCodeStart":258,"sourceCodeEnd":294,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix-attributes/src/search/outcome.rs#L258-L294","documentation":"During `MetadataCollection::update_from_list`, macro assignment patterns have their pattern text converted with `to_str().expect(\"valid macro names are always UTF8 and this was verified\")`. Macro names are validated as UTF-8 earlier in parsing, so this panic means a non-UTF-8 macro name reached the macro registration stage — a broken invariant between the parser's validation and this consumer.","triggerScenarios":"Loading an attributes file/buffer whose macro definition (`[attr]name ...`) contains non-UTF-8 bytes in the macro name, bypassing the parser-level UTF-8 verification — practically only via a parser regression or a mismatched gix-glob/gix-attributes version pair.","commonSituations":"Repositories with binary junk in .gitattributes files combined with a gix version whose parser failed to validate macro names; patched crates where validation was removed.","solutions":["Ensure macro names in .gitattributes are valid UTF-8 (they must be valid git attribute names anyway)","Upgrade gix-attributes and gix-glob together to versions from the same release","If you read attribute buffers yourself before add_patterns_buffer, validate UTF-8 of pattern text first","Report upstream with the offending .gitattributes content"],"exampleFix":"// caller-side guard before feeding buffers\nlet text = std::str::from_utf8(&buf)\n    .expect(\"attribute file must be UTF-8 for macro names\");\nsearch.add_patterns_buffer(text.as_bytes(), source, root, &mut collection, true);","handlingStrategy":"validation","validationCode":"// validate attribute buffers before handing them to the search\nfn valid_utf8_attributes(buf: &[u8]) -> bool { std::str::from_utf8(buf).is_ok() }","typeGuard":null,"tryCatchPattern":"std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| update_from_list(...)))","preventionTips":["Ensure .gitattributes files are UTF-8 encoded","Check git config for core attributes paths that may contain binary data","Keep gix-glob/gix-attributes versions aligned"],"tags":["rust","panic","utf8","macros","attributes"],"backgroundTag":"internal-invariant-violation","analyzedSha":"e73179060badf27222d790981fac3f84c1830a7e","analyzedAt":"2026-09-08T11:26:50.865Z","contentChangedAt":"2026-09-08T11:26:50.865Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}