{"record":{"id":"b3d004d064f6d272","repo":"BoundaryML/baml","slug":"name-should-always-be-defined-for-attribute","errorCode":null,"errorMessage":"Name should always be defined for attribute.","messagePattern":"Name should always be defined for attribute\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/baml-lib/ast/src/parser/parse_attribute.rs","lineNumber":45,"sourceCode":"        match current.as_rule() {\n            Rule::identifier => name = parse_identifier(current, diagnostics).into(),\n            Rule::path_identifier => name = parse_path_identifier(current, diagnostics).into(),\n            Rule::arguments_list => {\n                parse_arguments_list(current, &mut arguments, &name, diagnostics)\n            }\n            _ => parsing_catch_all(current, \"attribute\", diagnostics),\n        }\n    }\n\n    match name {\n        Some(name) => Attribute {\n            name,\n            arguments,\n            parenthesized,\n            span,\n        },\n        // This is suspicious, can probably cause a panic\n        None => unreachable!(\"Name should always be defined for attribute.\"),\n    }\n}\n","sourceCodeStart":27,"sourceCodeEnd":48,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/baml-lib/ast/src/parser/parse_attribute.rs#L27-L48","documentation":"parse_attribute builds an Attribute only when the attribute name pair exists; the None branch is marked unreachable!('Name should always be defined for attribute.'). It is an internal invariant assertion meaning the pest grammar guaranteed a name but the code saw none — a panic, not a catchable anyhow error.","triggerScenarios":"Calling parse_attribute with a token whose inner pairs are empty — only possible from a grammar/code desync (grammar changed so @attr name pair is optional) or a corrupted/partially built pair.","commonSituations":"Mixing crate versions where the pest grammar and parser hand-written code come from different builds; custom downstream builds of the ast crate.","solutions":["Use a consistent, released version of the baml ast crate (grammar + parser from the same build).","If reproducible on a released version, report the .baml snippet as a parser bug.","As a workaround, remove/rewrite the attribute that triggers the panic."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if let Some(attr) = pair.clone().into_inner().next() {\n    parse_attribute(attr)?;\n} else {\n    eprintln!(\"skipping degenerate attribute token\");\n}","typeGuard":"fn attribute_has_name(pair: &Pair<Rule>) -> bool {\n    pair.clone().into_inner().next().is_some()\n}","tryCatchPattern":"let result = std::panic::catch_unwind(|| parse_attribute(token));\nmatch result {\n    Ok(attr) => attr,\n    Err(_) => return Err(anyhow!(\"malformed attribute token\")),\n}","preventionTips":["Use stock, version-matched builds of the baml ast crate.","Avoid patching the grammar without updating parse_attribute.","Fuzz-test attribute parsing against the grammar to catch desyncs."],"tags":["rust","parser","panic","invariant"],"backgroundTag":"internal-invariant-violation","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}