BoundaryML/baml · error
field access on non-map/class at
Error message
field access on non-map/class at {:?} What it means
For a field-access expression `base.field`, the interpreter only supports Map and Class base values; a missing field on those yields "missing field", but any other base type (list, string, scalar) throws "field access on non-map/class at {:?}". Dot access is reserved for structural values.
Solutions
- Check the base value's actual type and use the correct access form (index for lists, direct value for scalars)
- If expecting a class, ensure the expression constructs/returns that class (e.g. correct ClassConstructor call)
- For lists, index elements first, then access fields on the element
- Validate LLM/parse output shape so the value is a class/map as expected
Example fix
// before let x = my_list.name // field access on non-map/class // after let x = my_list[0].name
Defensive patterns
Strategy: type-guard
Validate before calling
// Confirm the value supports field access before using dot syntax
function assertFieldAccess(v: unknown, field: string): void {
if (v === null || typeof v !== "object" || Array.isArray(v))
throw new Error(`Cannot access field '${field}' on ${Array.isArray(v) ? "list" : typeof v}`);
} Type guard
function isStruct(v: unknown): v is Record<string, unknown> {
return v !== null && typeof v === "object" && !Array.isArray(v);
} Try / catch
try {
return evalBaml(fieldExpr);
} catch (e) {
if (String(e).includes("field access on non-map/class")) {
throw new Error("Dot access requires a map or class — check the base value's type");
}
throw e;
} Prevention
- Validate parsed/LLM output shapes so fields live on classes/maps as expected
- Index list elements first, then access fields on the element
- Do not expect string/list methods or properties in BAML expressions
- Check function return types before chaining field access onto calls
When it happens
Trigger: Using dot syntax on a value that evaluates to a list, string, int, bool, or null — e.g. `my_list.first`, `"text".length` — instead of a map or class instance.
Common situations: Assuming strings or lists have properties/methods like in other languages; accessing a field on what you thought was a class but the LLM/parse produced a scalar; chaining off a function call that returns the wrong type.
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
- array access on non-list at
- array assignment on non-list value at
- attempted to call non-function
- bitwise ^= requires integer operands
- bitwise |= requires integer operands
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/20dc7b45ef40013e.
Report an issue: GitHub.
Appendix: source
Thrown at engine/baml-compiler/src/thir/interpret.rs:2055
base,
scopes,
thir,
run_llm_function,
watch_handler,
function_name,
)
.await?,
)?;
match b.clone() {
BamlValueWithMeta::Map(m, _) => {
let v = m.get(field).context("missing field")?;
EvalValue::Value(v.clone())
}
BamlValueWithMeta::Class(_, m, _) => {
let v = m.get(field).context("missing field")?;
EvalValue::Value(v.clone())
}
_ => bail!("field access on non-map/class at {:?}", meta.0),
}
}
Expr::ClassConstructor { name, fields, meta } => {
let mut field_map: BamlMap<String, BamlValueWithMeta<ExprMetadata>> =
BamlMap::new();
for field in fields {
match field {
ClassConstructorField::Named { name, value } => {
field_map.insert(
name.clone(),
expect_value(
evaluate_expr(
value,
scopes,
thir,
run_llm_function,
watch_handler,View on GitHub (pinned to bd85ce9dee)