BoundaryML/baml · error
class field count fits u32
Error message
class field count fits u32
What it means
While linking interface fields to class fields, the runtime slot index of a linked class field is narrowed to `u32` with `.expect("class field count fits u32")`. The panic means the class field slot index exceeded `u32::MAX`, which the runtime encoding cannot hold — practically indicating a slot-numbering bug rather than a real class with billions of fields.
Source
Thrown at baml_language/crates/baml_compiler2_emit/src/lib.rs:1143
spelling.wire(&qualify_def(db, Definition::Class(class), &class_item.name));
let class_slots = class_field_indices.get(&class_tn.to_string());
declared
.iter()
.map(|iface_field| {
let class_field = block
.field_links
.iter()
.find(|link| link.interface_field == *iface_field)
.map_or(iface_field, |link| &link.class_field);
let slot = class_slots
.and_then(|slots| slots.get(class_field.as_str()))
.copied();
debug_assert!(
slot.is_some(),
"interface `{iface_tn}` field `{iface_field}` links to \
`{class_tn}.{class_field}`, which has no runtime slot",
);
slot.map(|s| u32::try_from(s).expect("class field count fits u32"))
})
.collect()
}
};
let Some(field_links) = field_links else {
continue;
};
program_packages
.entry(spelling.of(pkg_info.root).clone())
.or_default()
.impl_rules
.entry(interface_head)
.or_default()
.push(ProgramImplRule {
interface_head,
for_ty_pattern,
generic_param_bounds,
interface_args,View on GitHub (pinned to bd85ce9dee)
Solutions
- Check the class field slot allocator for unbounded increments or double-counting
- Verify the debug_assert above it: the linked class field must actually have a runtime slot
- Clear incremental build caches and rebuild
- If huge field counts are legitimate, widen the slot encoding to u64 in VM types
Example fix
// before
slot.map(|s| u32::try_from(s).expect("class field count fits u32"))
// after
slot.map(|s| u32::try_from(s))
.transpose()
.map_err(|_| EmitError::TooManyClassFields(class_tn.clone()))? Defensive patterns
Strategy: validation
Validate before calling
if let Some(s) = slot {
if s > u32::MAX as usize {
return Err(CompilerBug::FieldSlotOverflow(class_tn.clone()));
}
} Type guard
fn fits_u32(n: usize) -> Option<u32> {
u32::try_from(n).ok()
} Try / catch
std::panic::catch_unwind(|| build_packages(db))
.unwrap_or_else(|_| report_compiler_bug("class field slot overflow")); Prevention
- Audit the slot allocator for unbounded increments when many classes are emitted
- Respect the neighboring debug_assert: a linked interface field must map to a real class slot
- Clear incremental caches after changes to field slot numbering
When it happens
Trigger: During `build_packages` field-link construction, `slot.map(|s| u32::try_from(s)...)` receives a slot index > u32::MAX — caused by runaway slot allocation or a corrupted/overflowed class field counter.
Common situations: Emitter bugs that increment slot counters without bound; generated classes with enormous field counts from code generation gone wrong; corrupted incremental caches.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- ntypeargs fits u16
- generic arity fits u32
- sys_op callee must resolve to a statically-known global func
- expected jump instruction at index {instruction_idx}
- exhaustive realized-leaf template classification
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/78528b9b1c7c056b.
Report an issue: GitHub.