BoundaryML/baml · error

exprs that evaluate to lambda

Error message

exprs that evaluate to lambda

What it means

This is a `todo!()` panic in `parse_expr_block` in the BAML AST parser. When the parser needs to decide whether the expression inside a block is a return value, it encounters an `Expression::Lambda` and explicitly aborts, because lambdas that appear as expressions evaluating in statement position are not yet supported. The preceding `// TODO: Is this possible?` comment confirms this is an intentionally unimplemented path, not a data corruption bug.

Source

Thrown at engine/baml-lib/ast/src/parser/parse_expr.rs:902

        | Expression::Paren(..) => true,

        // If the trailing expression happens to be a block, check if the
        // block itself has a trailing expression that produces a value.
        Expression::ExprBlock(block, _) => block.expr.is_some(),

        // If trailing expression is an if statement, check if the statment
        // itself has a trailing expression.
        Expression::If(_, if_branch, else_branch, _) => match if_branch.as_ref() {
            Expression::ExprBlock(block, _) => block.expr.is_some(),
            _ => match else_branch.as_ref().map(Box::as_ref) {
                Some(Expression::ExprBlock(block, _)) => block.expr.is_some(),
                // This should not happen since branches are always blocks.
                _ => true,
            },
        },

        // TODO: Is this possible?
        Expression::Lambda(..) => todo!("exprs that evaluate to lambda"),
    });

    // If the block actually returns a value, keep it as trailing expression.
    // Otherwise, promote the expression to a statement.
    let trailing_expr = if is_return_value {
        expr.map(Box::new)
    } else {
        if let Some(expr) = expr {
            stmts.push(Stmt::Expression(ExprStmt {
                expr: expr.clone(),
                annotations: vec![],
                span: expr.span().clone(),
            }));
        }

        None
    };

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Rewrite the BAML code so the block's trailing expression is not a lambda — assign the lambda to a variable or pass it directly as a function argument instead
  2. Return a concrete value (string, int, object) from the block rather than a function value
  3. Check the BAML changelog/releases for lambda-expression support and upgrade if implemented
  4. If you are a contributor: replace the `todo!()` with a proper rule for `Expression::Lambda` (decide is_return_value and emit diagnostics)

Example fix

// before (panics)
function F(x int) int {
  () => x + 1
}
// after
function F(x int) int {
  let f = (y int) => y + 1;
  f(x)
}
Defensive patterns

Strategy: validation

Validate before calling

// Reject lambdas in trailing/statement position before submitting to the parser:
function assertNoLambdaTail(blockSource) {
  if (/=>\s*(\{|[^\n]*$)/m.test(lastStatementOf(blockSource))) {
    throw new Error('Lambda as block trailing expression is unsupported and panics the BAML parser');
  }
}

Type guard

const isLambdaExpr = (expr) => typeof expr === 'string' && /=>/.test(expr);

Prevention

When it happens

Trigger: Parsing a BAML block (function body, if/while/for body, or statement block via `parse_expr_block`) whose trailing/statement expression is a lambda, e.g. `() => {...}` appearing where a value-returning expression is evaluated.

Common situations: Writing a BAML function whose last statement returns or evaluates a lambda; passing an anonymous function as the result of a block in a prompt-time expression; upgrading BAML and using lambda expressions in places the runtime does not yet handle.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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