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

  1. Ensure GC forwarding updates Package.enums pointers when enums move during sweep_and_forward.
  2. Don't cache enum pointers across GC cycles; re-read them from the package after each sweep.
  3. Audit unsafe code that could write non-enum objects into the package's enum table.
  4. 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

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


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/9a710dbfed29a202. Report an issue: GitHub.