{"record":{"id":"2954f6d6923694fb","repo":"BoundaryML/baml","slug":"field-access-must-be-on-classes-but-expr-got-other","errorCode":null,"errorMessage":"field access must be on classes, but expr `{}` got: {other:?}","messagePattern":"field access must be on classes, but expr `(.+?)` got: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/baml-compiler/src/codegen.rs","lineNumber":1200,"sourceCode":"                    Some(TypeIR::Class {\n                        name: class_name, ..\n                    }) => {\n                        let Some(_class_index) = self.globals.get(class_name) else {\n                            panic!(\"undefined class: {class_name}\");\n                        };\n\n                        let Some(resolved_fields) = self.classes.get(class_name) else {\n                            panic!(\"undefined class: {class_name}\");\n                        };\n\n                        let Some(&field_index) = resolved_fields.get(field) else {\n                            panic!(\"undefined field: {class_name}.{field}\");\n                        };\n\n                        self.emit(Instruction::LoadField(field_index));\n                    }\n\n                    other => panic!(\n                        \"field access must be on classes, but expr `{}` got: {other:?}\",\n                        base.dump_str()\n                    ),\n                }\n            }\n\n            thir::Expr::Var(name, _) => {\n                if let Some(&index) = self.locals.get(name) {\n                    self.emit(Instruction::LoadVar(index));\n                } else if let Some(class) = self.globals.get(name) {\n                    self.emit(Instruction::LoadGlobal(*class));\n                } else {\n                    panic!(\"undefined variable: {name}\");\n                }\n            }\n\n            thir::Expr::List(elements, _) => {\n                for element in elements {","sourceCodeStart":1182,"sourceCodeEnd":1218,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/baml-compiler/src/codegen.rs#L1182-L1218","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nlet v = myMap.key\n// after\nlet v = myMap[\"key\"]","handlingStrategy":"type-guard","validationCode":"// Only dot-access fields on class-typed bases\nmatch base_type {\n    TypeIR::Class { .. } => { /* field access allowed */ }\n    TypeIR::Map(..) => return Err(\"use [\\\"key\\\"] indexing for maps\"),\n    other => return Err(format!(\"cannot field-access {other:?}\")),\n}","typeGuard":"fn is_class_typed(t: &TypeIR) -> bool {\n    matches!(t, TypeIR::Class { .. })\n}","tryCatchPattern":null,"preventionTips":["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`"],"tags":["compiler","codegen","panic","field-access","types"],"backgroundTag":"type-mismatch","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}