BoundaryML/baml · error
unsupported statement type in C-for after clause
Error message
unsupported statement type in C-for after clause
What it means
Raised by the BAML interpreter when executing the after clause of a C-style for loop. Only two statement kinds are permitted there: plain `Assign` and compound `AssignOp`. If the after clause contains any other statement type (a function call statement, declaration, nested loop, expression statement handled as another variant, etc.), the interpreter bails with this message.
Source
Thrown at engine/baml-compiler/src/thir/interpret.rs:1166
thir,
run_llm_function,
watch_handler,
function_name,
)
.await?,
)?;
assign_to_expr(
left,
v,
scopes,
thir,
run_llm_function,
watch_handler,
function_name,
)
.await?;
}
_ => bail!(
"unsupported statement type in C-for after clause"
),
}
}
continue;
}
ControlFlow::Normal(_) => {
// Execute after statement if present
if let Some(after_stmt) = after {
// Execute the after statement in the current scope context
match after_stmt.as_ref() {
Statement::AssignOp {
left,
value,
assign_op,
..
} => {
use crate::hir::AssignOp;View on GitHub (pinned to bd85ce9dee)
Solutions
- Move any non-assignment logic out of the after clause and put it at the end of the loop body instead.
- Use a plain assignment in the after clause: `i = next(i)` style instead of a call statement.
- Restructure as a foreach/while-style loop if the update step is complex.
- Upgrade BAML to a version with broader after-clause support.
Example fix
// before (BAML)
for (let i = 0; i < n; log(i)) { ... }
// after
for (let i = 0; i < n; i += 1) { log(i); ... } Defensive patterns
Strategy: validation
Validate before calling
// Ensure the C-for update clause is a single assignment statement before running:
const isAssign = /^\s*[A-Za-z_]\w*(\.[A-Za-z_]\w*)*\s*(=(?!=)|\+=)\s*[^;]+;?\s*$/.test(afterClauseSrc);
if (!isAssign) throw new Error("C-for after clause must be `var = expr` or `var += expr`"); Prevention
- Never put function calls or declarations in the for-loop update clause.
- Keep side effects (logging, pushes) at the end of the loop body.
- Use foreach loops when the iteration step isn't a simple counter update.
- Review ported C/JS loops clause-by-clause before committing.
When it happens
Trigger: A BAML C-style for loop with a non-assignment statement in the third clause, e.g. `for (let i = 0; i < n; foo(i))`, a `let` declaration in the update position, or any statement the parser yields as something other than Assign/AssignOp.
Common situations: Porting C/JS update-clause expressions like `i++, arr.push(x)` or side-effecting calls into BAML's third for-clause; accidentally putting an initializer or body statement into the update slot.
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
- unsupported assign op in C-for after clause
- unsupported types for %= operator
- bitwise ^= requires integer operands
- bitwise &= requires integer operands
- bitwise |= requires integer operands
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/970b318729d44e1d.
Report an issue: GitHub.