BoundaryML/baml · error

Guaranteed by the grammar

Error message

Guaranteed by the grammar

What it means

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.

Source

Thrown at engine/baml-lib/ast/src/parser/parse_expression.rs:647

                )
            }
        })
        .next();

    if let Some(value) = value {
        value
    } else {
        unreachable!("Encountered impossible jinja expression during parsing")
    }
}

pub fn parse_class_constructor(token: Pair<'_>, diagnostics: &mut Diagnostics) -> Expression {
    assert_correct_parser(&token, &[Rule::class_constructor], diagnostics);

    let span = diagnostics.span(token.as_span());
    let mut tokens = token.into_inner();

    let ident_token = tokens.next().expect("Guaranteed by the grammar");

    let class_name = match ident_token.as_rule() {
        Rule::identifier => parse_identifier(ident_token, diagnostics),
        Rule::path_identifier => parse_path_identifier(ident_token, diagnostics),
        _ => panic!("Encountered impossible class constructor during parsing"),
    };

    let mut fields = Vec::new();
    while let Some(field_or_close_bracket) = tokens.next() {
        if field_or_close_bracket.as_str() == "}" {
            break;
        }
        if field_or_close_bracket.as_str() == "," {
            continue;
        }
        if field_or_close_bracket.as_rule() == Rule::NEWLINE {
            continue;
        }

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Inspect the class constructor syntax in your .bml file at the reported span (e.g. `ClassName {`) and correct it
  2. File a bug with the input that reproduces the panic — the grammar allows a tokenless class_constructor node
  3. Use a BAML version where the grammar and parser agree
  4. Run the pest grammar tests to regenerate/verify the class_constructor rule

Example fix

// before
let c = ;
// after
let c = MyClassName { field: value };
Defensive patterns

Strategy: validation

Validate before calling

// Ensure every class constructor reference has a name before parsing
fn class_constructors_named(src: &str) -> bool {
    // naive check: no bare `let x = {` without a preceding identifier
    !src.contains("= ;") && !src.lines().any(|l| l.trim_end().ends_with("= {".trim()) && false)
}
// Prefer: run `baml CLI check` to get diagnostics instead of parsing raw

Type guard

fn is_valid_class_ctor(stmt: &str) -> bool {
    let s = stmt.trim();
    s.starts_with("let ") && s.contains("=") && {
        let rhs = s.split('=').nth(1).unwrap_or("").trim();
        rhs.chars().next().map_or(false, |c| c.is_alphabetic() || c == '_')
    }
}

Try / catch

let result = std::panic::catch_unwind(|| parser.parse_class_constructor(pair, &mut diag));
if result.is_err() { eprintln!("parser bug: class constructor missing name token"); }

Prevention

When it happens

Trigger: parse_class_constructor invoked with a Rule::class_constructor pair whose into_inner() stream is empty — no identifier/path_identifier child token present.

Common situations: 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.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/830219a8c231f732. Report an issue: GitHub.