BoundaryML/baml · error

Filter function ' ' must take exactly 1 parameter (current…

Error message

Filter function '{}' must take exactly 1 parameter (current value)

What it means

Filter functions used with @watch must accept exactly one parameter — the current value of the watched variable. The interpreter validates arity before invoking the filter and aborts with this error when the declared function has any other number of parameters.

Solutions

  1. Change the filter function to take exactly one parameter (the current value)
  2. Move any additional data the filter needs into the function body or constants instead of extra parameters
  3. Rename to a different dedicated single-argument filter function and point the @watch attribute at it

Example fix

// before
function isLong(value: string, min: int) -> bool { ... }
// after
function isLong(value: string) -> bool { value.length() > 10 }
Defensive patterns

Strategy: validation

Validate before calling

fn validate_filter_arity(f: &FunctionDef) -> Result<(), String> {
    if f.parameters.len() == 1 { Ok(()) }
    else { Err(format!("filter '{}' must take exactly 1 parameter", f.name)) }
}

Type guard

fn is_valid_watch_filter(f: &FunctionDef) -> bool { f.parameters.len() == 1 }

Prevention

When it happens

Trigger: Declaring a filter function with 0 or 2+ parameters and referencing it from a @watch filter attribute; check_watch_changes then calls evaluate_filter_function, which enforces parameters.len() == 1.

Common situations: Writing a filter that also takes config/extra arguments; copy-pasting a multi-argument helper into a watch filter; forgetting to wrap extra context in a closure-like single-arg function.

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

Appendix: source

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

    scopes: &mut Vec<Scope>,
    thir: &THir<ExprMetadata>,
    run_llm_function: &mut F,
    function_name: &str,
) -> Result<bool>
where
    F: LlmHandler<Fut>,
    Fut: LlmFuture,
{
    // Look up the filter function
    let filter_func = thir
        .expr_functions
        .iter()
        .find(|f| f.name == fn_name.to_string())
        .with_context(|| format!("Filter function '{fn_name}' not found"))?;

    // Check arity
    if filter_func.parameters.len() != 1 {
        bail!(
            "Filter function '{}' must take exactly 1 parameter (current value)",
            fn_name
        );
    }

    // Convert BamlValue to BamlValueWithMeta
    log::debug!("Filter function current_value: {current_value:?}");
    let value_with_meta = baml_value_to_value_with_meta(current_value.clone());

    // Create a new scope with the function parameter
    // Mark this as a filter context to prevent infinite recursion
    scopes.push(Scope {
        variables: [(
            filter_func.parameters[0].name.clone(),
            Arc::new(Mutex::new(value_with_meta)),
        )]
        .into_iter()
        .collect(),

View on GitHub (pinned to bd85ce9dee)