BoundaryML/baml · error
field access must be on classes, but expr `{}` got: {other:?
Error message
field access must be on classes, but expr `{}` got: {other:?} What it means
Panic when the base of a field-access expression resolves to a type that is not a class (and not an enum handled earlier). Field access in this codegen is only defined for class-typed bases; any other resolved type reaches the `other =>` catch-all, which panics with the base expression's dumped source and its type. Type checking should have rejected non-class field accesses before codegen.
Source
Thrown at engine/baml-compiler/src/codegen.rs:1200
Some(TypeIR::Class {
name: class_name, ..
}) => {
let Some(_class_index) = self.globals.get(class_name) else {
panic!("undefined class: {class_name}");
};
let Some(resolved_fields) = self.classes.get(class_name) else {
panic!("undefined class: {class_name}");
};
let Some(&field_index) = resolved_fields.get(field) else {
panic!("undefined field: {class_name}.{field}");
};
self.emit(Instruction::LoadField(field_index));
}
other => panic!(
"field access must be on classes, but expr `{}` got: {other:?}",
base.dump_str()
),
}
}
thir::Expr::Var(name, _) => {
if let Some(&index) = self.locals.get(name) {
self.emit(Instruction::LoadVar(index));
} else if let Some(class) = self.globals.get(name) {
self.emit(Instruction::LoadGlobal(*class));
} else {
panic!("undefined variable: {name}");
}
}
thir::Expr::List(elements, _) => {
for element in elements {View on GitHub (pinned to bd85ce9dee)
Solutions
- Use bracket indexing (`base["key"]`) for map access instead of dot access
- Unwrap optional values before accessing fields
- Ensure the base expression actually evaluates to a class instance
- If the base is a valid class, report a compiler bug: resolved type metadata is wrong at codegen
Example fix
// before let v = myMap.key // after let v = myMap["key"]
Defensive patterns
Strategy: type-guard
Validate before calling
// Only dot-access fields on class-typed bases
match base_type {
TypeIR::Class { .. } => { /* field access allowed */ }
TypeIR::Map(..) => return Err("use [\"key\"] indexing for maps"),
other => return Err(format!("cannot field-access {other:?}")),
} Type guard
fn is_class_typed(t: &TypeIR) -> bool {
matches!(t, TypeIR::Class { .. })
} Prevention
- Use bracket indexing for map/list access, dot access only on class instances
- Unwrap optionals before field access
- Check the base expression's inferred type before writing `.field`
When it happens
Trigger: Compiling `Expr::FieldAccess` whose base resolves to a non-class, non-enum type — e.g. `.field` on a string, int, list, or optional value; or the base type metadata is missing/misresolved.
Common situations: Dot-accessing into a map or list instead of using indexing; accessing fields on primitives (e.g. `str.length` style not supported); optional bases that were not unwrapped before field access.
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
- Field access on non-class type
- undefined class: {class_name}
- undefined field: {class_name}.{field}
- array access should be either map or array.
- undefined function: {name}
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/2954f6d6923694fb.
Report an issue: GitHub.