BoundaryML/baml · error

Expected a , got a ( : )

Error message

Expected a {:?}, got a {:?} ({}:{})

What it means

The next_pair! macro asserts the next pest pair matches an expected Rule, skipping NEWLINE pairs. On mismatch it errors with 'Expected a {:?}, got a {:?} (file:line)'. It is a formatter-side structural invariant check on the parse tree.

Solutions

  1. Pin the baml ast/parser and formatter to matching versions (same crate release).
  2. Check the reported rule name in the message to locate the offending syntax in your .baml file and simplify it.
  3. Report a bug with the offending schema snippet if versions match — it is a grammar/formatter desync.
Defensive patterns

Strategy: try-catch

Try / catch

match format_schema(source, &options) {
    Ok(f) => f,
    Err(e) if e.to_string().starts_with("Expected a ") => {
        eprintln!("formatter/grammar desync: {e}");
        source.to_string()
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Any format_schema invocation where the pest parse tree shape deviates from what the formatter's macro expects — e.g. grammar changed but formatter macros not updated, or a rule matched in an unexpected position.

Common situations: Using a BAML grammar/parser version mismatched with the formatter, or formatting source with syntax that parses but in an ordering the formatter didn't anticipate.

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/b5135719ab11a05b. Report an issue: GitHub.

Appendix: source

Thrown at engine/baml-lib/ast/src/formatter/mod.rs:60

    let doc = formatter.schema_to_doc(schema_pair.into_inner())?;
    let mut w = Vec::new();
    doc.render(10, &mut w)
        .map_err(|_| anyhow!("Failed to render doc"))?;
    String::from_utf8(w).map_err(|_| anyhow!("Failed to convert to string"))
}

macro_rules! next_pair {
    ($pairs:ident, $rule:expr) => {{
        loop {
            match $pairs.peek() {
                Some(pair) => {
                    if pair.as_rule() == Rule::NEWLINE {
                        $pairs.next();
                        continue;
                    }
                    if pair.as_rule() != $rule {
                        break Err(anyhow!(
                            "Expected a {:?}, got a {:?} ({}:{})",
                            $rule,
                            pair.as_rule(),
                            file!(),
                            line!()
                        ));
                    } else {
                        $pairs.next();
                        break Ok(pair);
                    }
                }
                None => break Err(anyhow!("Expected a {}", stringify!($rule))),
            }
        }
    }};

    ($pairs:ident, $rule:expr, optional) => {{
        match $pairs.peek() {

View on GitHub (pinned to bd85ce9dee)