BoundaryML/baml · error · anyhow::Error

Expression functions must have a return type

Error message

Expression functions must have a return type

What it means

When converting an AST expression-function (fn defined as an expression/lambda) into IR type representation, the function must declare a return type. If expr_fn().return_type is None, BAML raises this error because it cannot construct the Arrow (function) type without a return type.

Source

Thrown at engine/baml-lib/baml-core/src/ir/repr.rs:251

                name,
            )
        });
        let tests = self
            .walk_tests()
            .map(|e| e.node(db))
            .collect::<Result<Vec<_>>>()?;
        let arg_types = args
            .iter()
            .map(|(_, arg_type)| arg_type.clone())
            .collect::<Vec<_>>();
        let arity = arg_types.len();
        let return_type = self
            .expr_fn()
            .return_type
            .clone()
            .map(|ret| ret.repr(db))
            .transpose()?
            .ok_or(anyhow::anyhow!(
                "Expression functions must have a return type"
            ))?;
        let lambda_type = TypeIR::Arrow(
            Box::new(ArrowGeneric {
                param_types: arg_types,
                return_type: return_type.clone(),
            }),
            Default::default(),
        );
        let expr_fn = ExprFunction {
            name: self.expr_fn().name.to_string(),
            inputs: args,
            output: return_type,
            expr: Expr::Lambda(
                arity,
                Arc::new(closed_body),
                (self.expr_fn().span.clone(), Some(lambda_type)),
            ),

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Add an explicit return type annotation to the expression function.
  2. Check the .baml function definition named in surrounding compiler output.
  3. Upgrade or align BAML CLI and runtime versions so syntax expectations match.

Example fix

// before
fn GetTopic(input string) {
  "pick a topic for {{ input }}"
}
// after
fn GetTopic(input string) -> string {
  "pick a topic for {{ input }}"
}
Defensive patterns

Strategy: validation

Validate before calling

# check expression fns declare a return type before compiling
import re
for m in re.finditer(r'^\s*fn\s+\w+\s*\([^)]*\)\s*(->\s*\w+)?\s*\{', src, re.M):
    if not m.group(1):
        print(f"missing return type: {m.group(0)!r}")

Try / catch

// add explicit return types; if this still fires, it's a compiler bug:
Err(e) if e.to_string().contains("must have a return type") => {
    eprintln!("add `-> Type` to the expression fn named in the error");
    return Err(e);
}

Prevention

When it happens

Trigger: Calling repr(db) on a function definition node whose expr_fn lacks a return type annotation — i.e. an expression-style `fn name(...) { ... }` written without `-> ReturnType`.

Common situations: Writing BAML expression functions without a return type annotation; older BAML syntax that allowed inferred return types being compiled by a newer stricter compiler.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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