BoundaryML/baml · error

cannot assign function to variable

Error message

cannot assign function to variable `{}`

What it means

In the BAML interpreter, a let statement binds a value to a new variable, but first-class function values cannot be stored in variables. When the evaluated right-hand side is EvalValue::Function, handle_statement bails out instead of creating the binding. (Assignment of function values is supported by codegen paths only in limited ways; the interpreter rejects it here.)

Solutions

  1. Call the function directly by name at each use site instead of aliasing it
  2. Replace the alias with an explicit conditional that calls the appropriate named function inline
  3. Restructure so the function is invoked where defined rather than passed/stored

Example fix

// before
let handler = on_event
handler(x)
// after
on_event(x)
Defensive patterns

Strategy: validation

Validate before calling

fn validate_let_value(v: &EvalValue, name: &str) -> Result<(), String> {
    match v { EvalValue::Function(_, _, _) => Err(format!("cannot assign function to '{}'", name)), _ => Ok(()) }
}

Type guard

fn is_assignable(v: &EvalValue) -> bool { !matches!(v, EvalValue::Function(_, _, _)) }

Prevention

When it happens

Trigger: Executing let name = <expression evaluating to a function> in interpreted code — e.g. let f = my_function or let f = if c { fn_a } else { fn_b }.

Common situations: Trying to alias functions for dynamic dispatch; translating higher-order patterns from other languages into BAML; refactoring shared call sites into a variable.

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

Appendix: source

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

                                    if let Some(var_ref) = lookup_variable(scopes, name) {
                                        register_watch_variable(
                                            scopes,
                                            name,
                                            var_ref,
                                            watch_spec.clone(),
                                        );
                                    }
                                }
                            }
                            EvalValue::Reference(cell) => {
                                declare_with_cell(scopes, name, cell.clone());
                                // Register watch tracking if @watch is present
                                if let Some(emit_spec) = watch {
                                    register_watch_variable(scopes, name, cell, emit_spec.clone());
                                }
                            }
                            EvalValue::Function(_, _, _) => {
                                bail!("cannot assign function to variable `{}`", name);
                            }
                        }
                        // Check for changes in all watch variables after the let statement
                        check_watch_changes(
                            scopes,
                            watch_handler,
                            function_name,
                            thir,
                            run_llm_function,
                        )
                        .await;
                    }
                    Statement::Declare { name, span } => {
                        declare(scopes, name, BamlValueWithMeta::Null((span.clone(), None)));
                    }
                    Statement::Assign { left, value } => {
                        let assigned_value = expect_value(
                            evaluate_expr(

View on GitHub (pinned to bd85ce9dee)