BoundaryML/baml · error
Cannot call expr function through call_function_impl
Error message
Cannot call expr function through call_function_impl
What it means
BAML expression functions (`expr`-based functions with no LLM prompt) cannot be executed through `call_function_impl`, which requires a real prepared LLM function with a prompt renderer and orchestration graph. The code explicitly rejects a prepared call whose `func` is None, which is the marker for expression functions.
Source
Thrown at engine/baml-runtime/src/runtime_methods/call_function.rs:53
},
runtime_interface::RuntimeConstructor,
tracing::BamlTracer,
tracingv2::storage::storage::{Collector, BAML_TRACER},
type_builder::TypeBuilder,
BamlRuntime, FunctionResult, FunctionResultStream, InternalRuntimeInterface,
RenderCurlSettings, RuntimeContext, RuntimeContextManager, TripWire,
};
impl BamlRuntime {
pub(crate) async fn call_function_impl<'ir>(
&'ir self,
prepared_func_call: PreparedFunction<'ir>,
ctx: RuntimeContext,
cancel_tripwire: Arc<TripWire>,
) -> Result<crate::FunctionResult> {
let future = async {
let func = prepared_func_call.func.as_ref().ok_or_else(|| {
anyhow::anyhow!("Cannot call expr function through call_function_impl")
})?;
let renderer = PromptRenderer::from_function(func, self.ir(), &ctx)?;
let orchestrator = self.orchestration_graph(renderer.client_spec(), &ctx)?;
let baml_args = BamlValue::Map(prepared_func_call.baml_args.value);
// Now actually execute the code.
let (history, _) = orchestrate_call(
orchestrator,
self.ir(),
&ctx,
&renderer,
&baml_args,
|s| renderer.parse(self.ir(), &ctx, s, false),
cancel_tripwire.trip_wire(),
)
.await;
View on GitHub (pinned to bd85ce9dee)
Solutions
- Route expr functions through the expr-aware path (`call_function_with_expr_events`) instead of `call_function` / call_function_impl.
- If the function should be an LLM function, restore its prompt/client definition in the BAML source so it is not treated as an expr function.
- Check the function's definition in baml_src: functions whose body is an expression are not streamable/callable via the generic LLM call path.
Example fix
// before
let result = runtime.call_function("my_expr_fn", params).await?; // panics into this error
// after
let result = runtime.call_function_with_expr_events("my_expr_fn", params).await?; Defensive patterns
Strategy: try-catch
Validate before calling
// Client code: only call generic call_function for LLM (non-expr) functions
if is_expr_function(runtime, "my_fn") {
return call_function_with_expr_events(runtime, "my_fn", params).await;
} Try / catch
// Rust
match runtime.call_function("my_fn", params).await {
Ok(r) => r,
Err(e) if e.to_string().contains("expr function") => {
runtime.call_function_with_expr_events("my_fn", params).await?
}
Err(e) => return Err(e.into()),
} Prevention
- Keep call sites in sync when refactoring BAML functions between prompt and expr forms.
- Route expr functions exclusively through expr-aware runtime APIs.
- Document per-function whether it is prompt-based or expr-based in your client layer.
When it happens
Trigger: Invoking a BAML expr function via the non-expr runtime path (e.g. a client/runtime `call_function` API, or call_function_with_expr_events when the prepared function turns out to be an expr function).
Common situations: A BAML function was refactored from an LLM prompt function into an expr function while client code still calls the generic function-call API; SDK callers using call_function on a function defined purely with `expr`.
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
- Cannot stream expr function through this code path
- {0}
- Invalid argument: {name}
- {message}
- Sentinel cannot be serialized
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/5bc30644dc2ae961.
Report an issue: GitHub.