{"record":{"id":"830219a8c231f732","repo":"BoundaryML/baml","slug":"guaranteed-by-the-grammar","errorCode":null,"errorMessage":"Guaranteed by the grammar","messagePattern":"Guaranteed by the grammar","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/baml-lib/ast/src/parser/parse_expression.rs","lineNumber":647,"sourceCode":"                )\n            }\n        })\n        .next();\n\n    if let Some(value) = value {\n        value\n    } else {\n        unreachable!(\"Encountered impossible jinja expression during parsing\")\n    }\n}\n\npub fn parse_class_constructor(token: Pair<'_>, diagnostics: &mut Diagnostics) -> Expression {\n    assert_correct_parser(&token, &[Rule::class_constructor], diagnostics);\n\n    let span = diagnostics.span(token.as_span());\n    let mut tokens = token.into_inner();\n\n    let ident_token = tokens.next().expect(\"Guaranteed by the grammar\");\n\n    let class_name = match ident_token.as_rule() {\n        Rule::identifier => parse_identifier(ident_token, diagnostics),\n        Rule::path_identifier => parse_path_identifier(ident_token, diagnostics),\n        _ => panic!(\"Encountered impossible class constructor during parsing\"),\n    };\n\n    let mut fields = Vec::new();\n    while let Some(field_or_close_bracket) = tokens.next() {\n        if field_or_close_bracket.as_str() == \"}\" {\n            break;\n        }\n        if field_or_close_bracket.as_str() == \",\" {\n            continue;\n        }\n        if field_or_close_bracket.as_rule() == Rule::NEWLINE {\n            continue;\n        }","sourceCodeStart":629,"sourceCodeEnd":665,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/baml-lib/ast/src/parser/parse_expression.rs#L629-L665","documentation":"An expect(\"Guaranteed by the grammar\") panic in parse_class_constructor. The parser assumes the class_constructor grammar rule always contains at least one child token (the class name identifier); if tokens.next() returns None the expect fires. This indicates a grammar/parser mismatch, i.e. a library bug, since malformed input should have failed grammar matching earlier.","triggerScenarios":"parse_class_constructor invoked with a Rule::class_constructor pair whose into_inner() stream is empty — no identifier/path_identifier child token present.","commonSituations":"Only realistically hit during BAML parser development or when a grammar change makes class constructor nodes with no name possible; user-facing syntax errors should instead surface as diagnostics.","solutions":["Inspect the class constructor syntax in your .bml file at the reported span (e.g. `ClassName {`) and correct it","File a bug with the input that reproduces the panic — the grammar allows a tokenless class_constructor node","Use a BAML version where the grammar and parser agree","Run the pest grammar tests to regenerate/verify the class_constructor rule"],"exampleFix":"// before\nlet c = ;\n// after\nlet c = MyClassName { field: value };","handlingStrategy":"validation","validationCode":"// Ensure every class constructor reference has a name before parsing\nfn class_constructors_named(src: &str) -> bool {\n    // naive check: no bare `let x = {` without a preceding identifier\n    !src.contains(\"= ;\") && !src.lines().any(|l| l.trim_end().ends_with(\"= {\".trim()) && false)\n}\n// Prefer: run `baml CLI check` to get diagnostics instead of parsing raw","typeGuard":"fn is_valid_class_ctor(stmt: &str) -> bool {\n    let s = stmt.trim();\n    s.starts_with(\"let \") && s.contains(\"=\") && {\n        let rhs = s.split('=').nth(1).unwrap_or(\"\").trim();\n        rhs.chars().next().map_or(false, |c| c.is_alphabetic() || c == '_')\n    }\n}","tryCatchPattern":"let result = std::panic::catch_unwind(|| parser.parse_class_constructor(pair, &mut diag));\nif result.is_err() { eprintln!(\"parser bug: class constructor missing name token\"); }","preventionTips":["Always give class constructors an identifier name in .bml files","Validate .bml with the BAML CLI before programmatic parsing","Avoid editing the .pest grammar without updating parser match arms","Pin BAML versions; test .bml files after upgrades"],"tags":["parser","rust","panic","grammar","internal-bug"],"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-14T11:17:12.474Z"}