pydantic/monty · error
class member '{member_name}' missing from class-body locals
Error message
class member '{member_name}' missing from class-body locals What it means
After preparing a class body, every declared class member must exist in the class-body scope's local slot map. If a member's name has no slot, class preparation panics — the members pass and the locals pass disagree about what the class body defines. It is an internal compiler invariant, not a user-facing error.
Source
Thrown at crates/monty/src/prepare.rs:1807
};
let FunctionState {
locals: inner_locals,
free_var_map: inner_free_var_map,
cell_var_map: inner_cell_var_map,
..
} = *inner_state;
let namespace_size = inner_locals.len();
drop(inner_prepare);
// Resolve each member to its class-body-local slot. Every member is
// assigned in the class body (a method `def` or a class-var `Assign`),
// so it is always present as a plain local.
let members = members
.into_iter()
.map(|member| {
let slot = inner_locals.get(member.name_id).unwrap_or_else(|| {
let member_name = self.interner.get_str(member.name_id);
panic!("class member '{member_name}' missing from class-body locals")
});
Identifier::new_with_scope(member.name_id, member.position, slot, NameScope::Local)
})
.collect::<Vec<_>>();
// Same-name collision (a known divergence — see `limitations/classes.md`):
// a class-body owned cell means a method captured a class-body local that
// ALSO has the same name as a variable in an enclosing scope. CPython keeps
// these distinct (class-dict entry vs. closure cell); Monty maps one name
// to a single slot, so it cannot represent both. Reject cleanly rather than
// miscompile (the alternative is a runtime "expected cell reference" crash).
if let Some(&name_id) = inner_cell_var_map.keys().next() {
let name_str = self.interner.get_str(name_id);
return Err(ParseError::not_implemented(
format!(
"class member '{name_str}' that shadows a captured variable of the same name from an enclosing scope"
),
position,View on GitHub (pinned to adc986b362)
Solutions
- Fix member collection so it only reports names the class-body locals pass registers.
- Ensure the class-body scope analysis runs before members are mapped to slots.
- Reduce the failing class definition and compare slot registration against member enumeration.
Example fix
// before
let slot = inner_locals.get(member.name_id).unwrap_or_else(|| panic!("class member missing"));
// after
// ensure member enumeration uses the same pass that fills inner_locals
let members = collect_class_members(&body); // shared source of truth
let slot = inner_locals.get(member.name_id).unwrap_or_else(|| panic!("class member '{member_name}' missing from class-body locals")); Defensive patterns
Strategy: validation
Validate before calling
// derive members and locals from the same AST pass
let members = collect_class_members(&body);
for m in &members { assert!(inner_locals.contains_key(m.name_id)); } Prevention
- Use one shared pass for member enumeration and local registration
- Test class bodies with del, conditional defs and walrus expressions
- Keep class preparation tests in the consolidated class test files
When it happens
Trigger: Compiling a class whose members list (from AST analysis) contains a name the class-body scope never registered as a local — e.g. names introduced by exotic statements inside the class body, or a mismatch introduced by changes to member collection.
Common situations: Contributors modifying class-body preparation or member enumeration; Python test code with unusual class bodies (del statements, conditional defs, walrus in class scope).
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- free_var '{name_str}' not found in enclosing scope's cells,
- bubble-up captured '{name_str}' that is bound nowhere — scop
- cycle values are not hashable
- {} python values are not hashable
- gather commit frame id is not a GatherFuture
AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13).
Data as JSON: /api/errors/b568b5e8ed667c88.
Report an issue: GitHub.