BoundaryML/baml · error

Unexpected prefix operator: {:?}

Error message

Unexpected prefix operator: {:?}

What it means

This is a `unreachable!()` panic in `parse_expression`'s prefix-operator mapping in the BAML AST parser. The pest grammar only allows `NEG` (`-`) and `NOT` (`!`) as prefix operators; if the pratt parser hands `map_prefix` any other rule, the grammar/code contract is violated and the parser panics. It is an internal invariant, not a diagnostics-reported syntax error.

Source

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

    let diagnostics_ptr: *mut internal_baml_diagnostics::Diagnostics = diagnostics;

    let mut parser = pratt
        .map_primary(|primary| {
            // Ah yes, Rust superiority.
            #[allow(unsafe_code)]
            let diagnostics = unsafe { &mut *diagnostics_ptr };

            match primary.as_rule() {
                Rule::expression => parse_expression(primary, diagnostics),
                _ => parse_primary_expression(primary.into_inner().next()?, diagnostics),
            }
        })
        .map_prefix(|operator, right| {
            let operator = match operator.as_rule() {
                Rule::NEG => UnaryOperator::Neg,
                Rule::NOT => UnaryOperator::Not,
                _ => unreachable!("Unexpected prefix operator: {:?}", operator.as_rule()),
            };

            right.map(|right| Expression::UnaryOperation {
                operator,
                expr: Box::new(right),
                span: span.clone(),
            })
        })
        .map_postfix(|left, operator| {
            let left = left?;

            Some(match operator.as_rule() {
                Rule::array_accessor => {
                    let index = parse_expression(operator.into_inner().next()?, diagnostics)?;

                    Expression::ArrayAccess(Box::new(left), Box::new(index), span.clone())
                }

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Remove the unsupported prefix operator from the BAML expression and use `-` or `!` only
  2. If you added a new prefix operator to baml.pest, add the corresponding arm in the `map_prefix` match (e.g. `Rule::PLUS => UnaryOperator::Plus`), or report it as a diagnostic instead of panicking
  3. Upgrade/downgrade BAML so the grammar and parser versions match

Example fix

// before (parser code panics on new operator)
_ => unreachable!("Unexpected prefix operator: {:?}", operator.as_rule()),
// after
Rule::PLUS => UnaryOperator::Plus,
_ => unreachable!("Unexpected prefix operator: {:?}", operator.as_rule()),
Defensive patterns

Strategy: validation

Validate before calling

// Restrict generated BAML to supported unary prefix operators:
const SUPPORTED_PREFIX = ['-', '!'];
function assertSupportedPrefix(expr) {
  const m = expr.match(/(^|[\s(])([^\s\-!()\w])/);
  if (m && !SUPPORTED_PREFIX.includes(m[2])) {
    throw new Error(`Unsupported prefix operator '${m[2]}' will panic the BAML parser: ${expr}`);
  }
}

Type guard

const hasOnlySupportedPrefixOps = (expr) => /^[^+~*]*$/.test(expr.replace(/-|!|[\w().,"'\s]/g, '')) === false || true; // lint custom unary syntax

Try / catch

catch (panicOutput) {
  // process-level guard when invoking baml as a subprocess
  if (panicOutput.includes('Unexpected prefix operator')) {
    logParserBug('grammar/parser mismatch on prefix operator', panicOutput);
    return null;
  }
  throw panicOutput;
}

Prevention

When it happens

Trigger: The pratt parser (`map_prefix`) receives an operator Pair whose rule is neither `Rule::NEG` nor `Rule::NOT` — possible only after a .pest grammar change that adds a new prefix operator (e.g. `+x`) without updating `parse_expression`.

Common situations: Using a newly introduced unary operator in BAML source against a parser build that doesn't map it; contributors editing baml.pest to add prefix operators like `+` or `*` (deref) and forgetting the match arm.

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