BoundaryML/baml · error

use_last_expr_as_return is true but last statement is not Ex

Error message

use_last_expr_as_return is true but last statement is not Expression

What it means

This is an internal invariant violation (an `unreachable!()` panic) in evaluate_block_with_control_flow. The flag use_last_expr_as_return is only supposed to be set when the block's last statement is an Expression statement; if the last statement is anything else (assignment, loop, return, etc.) while the flag is still set, the interpreter panics with this message. It indicates a compiler/interpreter bug, not user error.

Source

Thrown at engine/baml-compiler/src/thir/interpret.rs:1382

                .await?,
            )?
        } else if use_last_expr_as_return {
            // No explicit trailing expression, but last statement is an expression statement,
            // so use that as the implicit return value (handles cases like if-else at the end of a block)
            if let Some(Statement::Expression { expr, .. }) = block.statements.last() {
                expect_value(
                    evaluate_expr(
                        expr,
                        scopes,
                        thir,
                        run_llm_function,
                        watch_handler,
                        function_name,
                    )
                    .await?,
                )?
            } else {
                unreachable!("use_last_expr_as_return is true but last statement is not Expression")
            }
        } else {
            // No trailing expression and last statement is not an expression, return null
            BamlValueWithMeta::Null((internal_baml_diagnostics::Span::fake(), None))
        };
        scopes.pop();
        Ok(ControlFlow::Normal(ret))
    })
}

async fn evaluate_block<F, Fut>(
    block: &Block<ExprMetadata>,
    scopes: &mut Vec<Scope>,
    thir: &THir<ExprMetadata>,
    run_llm_function: &mut F,
    watch_handler: &SharedWatchHandler,
    function_name: &str,
) -> Result<BamlValueWithMeta<ExprMetadata>>

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Add an explicit final expression (or explicit `return`) as the last statement of the block so the implicit-return path is entered only with an Expression last statement.
  2. Check for a trailing non-expression statement (assignment, loop) at the end of the block and move or restructure it.
  3. Pin/downgrade to the previous BAML version if this appeared after an upgrade, and file a bug with the minimal reproducing BAML code.
  4. Upgrade to the latest BAML — this unreachable path may already be fixed.

Example fix

// before (BAML)
let r = if (x) { total += 1 } else { 0 };
// after
let r = if (x) { total += 1; total } else { 0 };
Defensive patterns

Strategy: fallback

Try / catch

// This is an internal panic; catch broadly and degrade:
try {
  return await bamlFn(ctx, args);
} catch (e) {
  if (String(e).includes("use_last_expr_as_return")) {
    logBug("baml interpreter invariant violation — file a bug with this input");
    return legacyPath(args);
  }
  throw e;
}

Prevention

When it happens

Trigger: A BAML expression block evaluated with implicit-return semantics (use_last_expr_as_return=true) whose final statement is not an Expression — e.g. a block ending in an assignment, a for loop, or a watch statement where the compiler incorrectly enabled implicit return. Also occurs when an early `return` inside the block drains the statement list unexpectedly.

Common situations: Hitting this while using newer BAML expression-language features (blocks with implicit returns, if-else as final statement) on code shapes the interpreter doesn't yet handle; usually reported as a bug after upgrading the BAML version.

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