BoundaryML/baml · error
Package.enums only contains enum pointers
Error message
Package.enums only contains enum pointers
What it means
`package_enum_type` mirrors `package_class_type` for enums: it builds a reflected type from a pointer stored in `Package.enums`, asserting it always points to an `Object::Enum`. The `unreachable!` means the enum table contained a pointer to some other object — a corrupted or stale (un-forwarded) heap pointer, since the loader only stores enum pointers there.
Source
Thrown at baml_language/crates/bex_vm/src/package_reflect/reflect.rs:308
bex_vm_types::TypeHead::new(class_ptr, class.type_tag),
Box::new([]),
class.ty_attr.clone(),
);
let ty_value = Value::object(vm.tlab.alloc_type(TypeValue::new(ty)));
super::type_kinds::alloc_kind_view(vm, baml_type::type_kind::TypeKind::Class, ty_value)
}
fn package_enum_type(vm: &mut BexVm, runtime_type: Option<HeapPtr>, enum_ptr: HeapPtr) -> Value {
if let Some(runtime_type) = runtime_type {
let ty_value = Value::object(runtime_type);
return super::type_kinds::alloc_kind_view(
vm,
baml_type::type_kind::TypeKind::Enum,
ty_value,
);
}
let Object::Enum(enm) = vm.get_object(enum_ptr) else {
unreachable!("Package.enums only contains enum pointers")
};
let ty = RealizedTy::Enum(
bex_vm_types::TypeHead::new(enum_ptr, enm.type_tag),
enm.ty_attr.clone(),
);
let ty_value = Value::object(vm.tlab.alloc_type(TypeValue::new(ty)));
super::type_kinds::alloc_kind_view(vm, baml_type::type_kind::TypeKind::Enum, ty_value)
}
fn package_interface_type(
vm: &mut BexVm,
runtime_type: Option<HeapPtr>,
interface_ptr: HeapPtr,
) -> Value {
if let Some(runtime_type) = runtime_type {
let ty_value = Value::object(runtime_type);
return super::type_kinds::alloc_kind_view(
vm,View on GitHub (pinned to bd85ce9dee)
Solutions
- Ensure GC forwarding updates Package.enums pointers when enums move during sweep_and_forward.
- Don't cache enum pointers across GC cycles; re-read them from the package after each sweep.
- Audit unsafe code that could write non-enum objects into the package's enum table.
- Run GC/reflection tests to reproduce and fix the forwarding regression.
Example fix
// before let enum_ptr = pkg.enums(vm)[0]; forward_objects(); let ty = package_enum_type(vm, enum_ptr); // stale pointer panics // after let enum_ptr = forwarding.get(&enum_ptr).copied().unwrap_or(enum_ptr); let ty = package_enum_type(vm, enum_ptr);
Defensive patterns
Strategy: validation
Validate before calling
fn is_enum(vm: &BexVm, p: HeapPtr) -> bool { matches!(vm.get_object(p), Object::Enum(_)) } Type guard
fn as_enum<'a>(vm: &'a BexVm, p: HeapPtr) -> Option<&'a Enum> {
match vm.get_object(p) { Object::Enum(e) => Some(e), _ => None }
} Prevention
- Ensure sweep_and_forward updates Package.enums pointers when enums move.
- Don't cache enum heap pointers across collections; fetch them fresh per reflection call.
- Run the GC/reflection test suite after any change to object forwarding.
When it happens
Trigger: Calling `package_enum_type` (via `get_enum`/`enums`) when an enum slot in the package holds a moved, swept, or otherwise invalid pointer whose target object is no longer an `Object::Enum` — usually after GC forwarding failed to update the stored pointer.
Common situations: Reflection over Package.enums after a GC sweep without pointer forwarding; heap corruption from unsafe writes; tests that cache enum pointers across collection cycles.
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
- Package.classes only contains class pointers
- live owner must be forwarded
- Package.current call site names a loaded package
- no-color diagnostics do not invoke the message highlighter
- rendering without a message highlighter cannot fail semantic
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/9a710dbfed29a202.
Report an issue: GitHub.