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
- Remove the unsupported prefix operator from the BAML expression and use `-` or `!` only
- 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
- 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
- Use only `-` and `!` as unary operators in BAML expressions
- When adding prefix operators to baml.pest, always extend the map_prefix match in parse_expression.rs in the same PR
- Keep grammar and parser crates version-aligned
- Add unit tests that parse every operator in the grammar
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
- Name should always be defined for attribute.
- Encountered impossible doc comment during parsing: {:?}, {:?
- c_for_init_stmt cannot accept empty input
- c_for_after_stmt cannot accept empty input
- block aware tail expression is not empty
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/a0e2f760bd2a5c61.
Report an issue: GitHub.