BoundaryML/baml · error · anyhow::Error

Enum not found for variant

Error message

Enum not found for variant: {:?}

What it means

from_vm_object converts a VmObject::Variant into a test-facing Object. Before reading the variant's name it dereferences the variant's enum handle from the VM object heap, expecting an enum. If the handle does not point to a VmObject::Enum, the internal representation is corrupt or the wrong object index was stored, so this bail fires.

Solutions

  1. Fix the code that constructs VmObject::Variant to store the correct enum index in the `enm` field
  2. Dump vm.objects[variant.enm] at the failure point to identify what type the index actually points to
  3. Check for GC/heap-compaction code that may invalidate Variant.enm indices
  4. Add a debug assertion when constructing variants that the handle resolves to VmObject::Enum

Example fix

// before
let VmObject::Enum(vm_enum) = &vm.objects[variant.enm] else {
    anyhow::bail!("Enum not found for variant: {:?}", variant);
};
// after
let Some(vm_enum) = vm.objects.get(variant.enm) else {
    anyhow::bail!("Enum index {} out of bounds for variant: {:?}", variant.enm, variant);
};
let VmObject::Enum(vm_enum) = vm_enum else {
    anyhow::bail!("Handle {:?} points to {:?}, expected enum", variant.enm, vm_enum);
};
Defensive patterns

Strategy: type-guard

Validate before calling

fn is_enum_handle(vm: &Vm, idx: usize) -> bool {
    matches!(vm.objects.get(idx), Some(VmObject::Enum(_)))
}

Type guard

if let VmObject::Enum(vm_enum) = &vm.objects[variant.enm] { /* use vm_enum */ } else { /* skip or log */ }

Try / catch

let obj = Object::from_vm_object(vm, variant).map_err(|e| { log::warn!("variant conversion failed: {e}"); e })?;

Prevention

When it happens

Trigger: Calling from_vm_object on a VmObject::Variant whose `enm` field indexes a non-Enum object in vm.objects (e.g. a class or instance), typically due to a compiler/VM bug writing the wrong index into Variant.enm.

Common situations: VM developers testing watch/notification serialization after changing the layout of VmObject variants or enum heap indexing; stale indices after GC or heap compaction changes.

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/0c9ddc3e25ecc7f5. Report an issue: GitHub.

Appendix: source

Thrown at engine/baml-vm/src/test.rs:119

                    anyhow::bail!("Class not found for instance: {:?}", instance);
                };

                let mut fields = BamlMap::new();

                for (i, value) in instance.fields.iter().enumerate() {
                    let value = Value::from_vm_value(value, vm)?;
                    fields.insert(vm_class.field_names[i].clone(), value);
                }

                Ok(Object::Instance(Instance {
                    class: vm_class.name.clone(),
                    fields,
                }))
            }

            VmObject::Variant(variant) => {
                let VmObject::Enum(vm_enum) = &vm.objects[variant.enm] else {
                    anyhow::bail!("Enum not found for variant: {:?}", variant);
                };

                Ok(Object::Variant(Variant {
                    enm: vm_enum.name.clone(),
                    variant: vm_enum.variant_names[variant.index].clone(),
                }))
            }

            VmObject::Media(media) => Ok(Object::Media(media.clone())),

            VmObject::Function(f) => Ok(Object::Function(f.name.clone())),

            VmObject::Class(c) => Ok(Object::Class(c.name.clone())),

            VmObject::Enum(e) => Ok(Object::Enum(e.name.clone())),

            _ => anyhow::bail!("Unsupported object type for testing: {:?}", obj),
        }

View on GitHub (pinned to bd85ce9dee)