BoundaryML/baml · error

push() can only be called on a variable at

Error message

push() can only be called on a variable at {:?}

What it means

The mutating array method `push()` must be invoked on a variable (an lvalue the interpreter holds as a mutable reference cell). If evaluating the receiver does not yield an `EvalValue::Reference` — e.g. it is a temporary value or a literal — the interpreter cannot mutate it and throws.

Solutions

  1. Assign the array to a variable first, then call push on that variable
  2. If the array comes from a function, store the result: `let xs = getItems(); xs.push(x);`
  3. For immutable use, rebuild the list with concatenation instead of push

Example fix

// before
[1, 2].push(3)
// after
let arr = [1, 2];
arr.push(3);
Defensive patterns

Strategy: validation

Validate before calling

// receiver must be a variable before push
if (!isVariableNode(receiverExpr)) { throw new Error('assign to a variable before calling push'); }

Try / catch

try { arr.push(x); } catch (e) { if (String(e).includes('push() can only be called on a variable')) { /* bind to variable and retry */ } else { throw e; } }

Prevention

When it happens

Trigger: Calling `push` on anything that is not a variable: a literal array `[1,2].push(3)`, the result of another expression/function call `getList().push(x)`, or a field access not backed by a cell.

Common situations: Trying to append to a function's return value inline; appending to an array literal; pushing onto a value returned from a map/filter pipeline instead of a stored 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/d792a5f9e649cf5a. Report an issue: GitHub.

Appendix: source

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

                    _ => bail!("method name must be an identifier at {:?}", meta.0),
                };

                // For mutating methods like push(), we need the cell reference
                if method_name == "push" {
                    // Get the receiver as a reference (cell) if possible
                    let receiver_eval = evaluate_expr(
                        receiver,
                        scopes,
                        thir,
                        run_llm_function,
                        watch_handler,
                        function_name,
                    )
                    .await?;

                    let receiver_cell = match receiver_eval {
                        EvalValue::Reference(cell) => cell,
                        _ => bail!("push() can only be called on a variable at {:?}", meta.0),
                    };

                    // Evaluate arguments
                    let mut arg_vals: Vec<BamlValueWithMeta<ExprMetadata>> =
                        Vec::with_capacity(args.len());
                    for arg in args.iter() {
                        arg_vals.push(expect_value(
                            evaluate_expr(
                                arg,
                                scopes,
                                thir,
                                run_llm_function,
                                watch_handler,
                                function_name,
                            )
                            .await?,
                        )?);
                    }

View on GitHub (pinned to bd85ce9dee)