BoundaryML/baml · error
expressions that evaluate to functions are not supported yet
Error message
expressions that evaluate to functions are not supported yet
What it means
BAML function-call compilation only supports calling a function by name (an identifier expression). If the callee expression is anything else — an arbitrary expression that evaluates to a function value — the code generator panics because first-class function values are not yet supported in this compiler path. Note the interpreter (THIR interpret) does support function values, so this is a codegen-only limitation.
Source
Thrown at engine/baml-compiler/src/codegen.rs:1248
self.compile_expression(value);
}
for (key, _) in pairs {
self.emit_string_literal(key);
}
self.emit(Instruction::AllocMap(pairs.len()));
}
thir::Expr::Call {
func,
args,
type_args,
..
} => {
let name = match func.as_ref() {
thir::Expr::Var(name, _) => name,
_ => panic!("expressions that evaluate to functions are not supported yet"),
};
// Push the function onto the stack
if let Some(&index) = self.globals.get(name) {
self.emit(Instruction::LoadGlobal(index));
} else {
panic!("undefined function: {name}");
}
// Push the arguments onto the stack
for arg in args {
self.compile_expression(arg);
}
// Type parameter. TODO: Generic way of handling this?
if name == "baml.fetch_as" {
let type_index = self.objects.insert(Object::BamlType(type_args[0].clone()));
let const_index = self.add_constant(Value::Object(type_index));View on GitHub (pinned to bd85ce9dee)
Solutions
- Call the function directly by its identifier name instead of via an intermediate expression
- Bind the result differently: call the function where its name is in scope rather than passing/deriving the callee dynamically
- If you need dynamic dispatch, use explicit branching (if/else calling named functions)
- Track BAML compiler releases for first-class function support; this is an explicit 'not supported yet' limitation
Example fix
// before let f = my_function f(args) // after my_function(args)
Defensive patterns
Strategy: validation
Validate before calling
fn validate_call_target(expr: &Expr) -> Result<(), String> {
match expr { Expr::Var(_) => Ok(()), _ => Err("callee must be a named function identifier".into()) }
} Type guard
fn is_named_callee(expr: &Expr) -> bool { matches!(expr, Expr::Var(_, _)) } Prevention
- Never assign functions to variables or expressions in compiled BAML code
- Always invoke functions directly by identifier
- Avoid higher-order function patterns until first-class functions are supported
- Review BAML release notes for function-value support before using dynamic callee patterns
When it happens
Trigger: Compiling a Call expression whose func field is not Expr::Var, e.g. calling the result of an expression like (get_fn())(...), calling a function stored in a variable, or invoking a method expression directly rather than via method-call syntax.
Common situations: Porting interpreter-friendly BAML (assigning functions to intermediate expressions) to compiled bytecode; attempting higher-order function calls in generated code; refactors that replaced a direct function name with an expression.
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
- Field access on non-class type
- undefined class: {class_name}
- undefined field: {class_name}.{field}
- array access should be either map or array.
- undefined function: {name}
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/a7801febaa248523.
Report an issue: GitHub.