BoundaryML/baml · error
array access should be either map or array.
Error message
array access should be either map or array.
What it means
A panic during codegen of an element-assignment statement: the compiler matched the resolved type of the indexed base expression expecting List or Map, and hit anything else (e.g. a primitive, string, or class type). The type resolution metadata lacked a List/Map type where indexed assignment was used.
Source
Thrown at engine/baml-compiler/src/codegen.rs:621
let Some(&field_index) = resolved_fields.get(field) else {
panic!("undefined field: {class_name}.{field}");
};
// Generate bytecode: load base, load value, store field
self.compile_expression(base);
self.compile_expression_with_block_behavior(value, true);
self.emit(Instruction::StoreField(field_index));
}
thir::Expr::ArrayAccess {base, index, meta: _} => {
self.compile_expression(base);
self.compile_expression(index);
self.compile_expression_with_block_behavior(value, true);
self.emit(match base.meta().1.as_ref().expect("must have a resolved type") {
TypeIR::List(_, _) => Instruction::StoreArrayElement,
TypeIR::Map(_, _, _) => Instruction::StoreMapElement,
_ => panic!("array access should be either map or array.")
});
}
_ => panic!("Invalid left hand of assignment, only variables, instance fields and array elements can be assigned"),
}
}
thir::Statement::AssignOp {
left,
value,
assign_op,
..
} => {
let binop = match assign_op {
hir::AssignOp::AddAssign => Instruction::BinOp(BinOp::Add),
hir::AssignOp::SubAssign => Instruction::BinOp(BinOp::Sub),
hir::AssignOp::MulAssign => Instruction::BinOp(BinOp::Mul),
hir::AssignOp::DivAssign => Instruction::BinOp(BinOp::Div),
hir::AssignOp::ModAssign => Instruction::BinOp(BinOp::Mod),View on GitHub (pinned to bd85ce9dee)
Solutions
- Ensure the indexed variable is declared/typed as a list or map in BAML
- Fix the variable's type annotation or initializer
- If the resolved type is legitimately missing, report a compiler bug to the BAML maintainers
Example fix
// before let name = "hello" name[0] = 'H' // after let chars = ["h", "e", "l", "l", "o"] chars[0] = "H"
Defensive patterns
Strategy: validation
Validate before calling
fn ensure_indexable(t: &TypeIR) -> Result<(), String> {
match t {
TypeIR::List(_, _) | TypeIR::Map(_, _, _) => Ok(()),
other => Err(format!("cannot index-assign into type {:?}", other)),
}
} Type guard
fn is_indexable(t: Option<&TypeIR>) -> bool {
matches!(t, Some(TypeIR::List(_, _)) | Some(TypeIR::Map(_, _, _)))
} Prevention
- Only use index assignment on declared lists/maps
- Check inferred types when refactoring variables
- Avoid treating strings as indexable in BAML
When it happens
Trigger: `arr[i] = v` where `arr`'s resolved type is neither List nor Map; unresolved type metadata; assigning into a string or scalar via index syntax.
Common situations: Index-assigning into a non-collection variable after a type change; code where type inference marked the variable as a different kind; strings mistakenly treated as indexable.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- undefined field: {class_name}.{field}
- undefined function: {name}
- watch codegen error: undefined variable: {variable}
- sys_op callee must resolve to a statically-known global func
- expected jump instruction at index {instruction_idx}
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/14b6d5e137e55213.
Report an issue: GitHub.