BoundaryML/baml · error

Map.delete: should be dispatched via __glue_delete

Error message

Map.delete: should be dispatched via __glue_delete

What it means

`Map.delete` is a placeholder that always panics: deletion must be dispatched via the `__glue_delete` glue method, which owns the mutable VM access required to remove entries. The raw `delete` function only exists as a table placeholder and must never be invoked.

Solutions

  1. Fix the dispatch table so `Map.delete` resolves to `__glue_delete`.
  2. In BAML code, use map delete syntax (map.remove(key) or equivalent) rather than raw native calls.
  3. Rebuild/upgrade bex_vm if seen in a released build.

Example fix

// before
"delete" => NativeFn::Raw(map::delete),
// after
"delete" => NativeFn::Glue(map::__glue_delete),
Defensive patterns

Strategy: validation

Validate before calling

assert!(dispatch_table.get("delete") == Some(&NativeFn::Glue(map::__glue_delete)));

Try / catch

// Rust panic — guard via a startup registration test for map methods.

Prevention

When it happens

Trigger: Method dispatch routing `Map.delete` to the raw function instead of `__glue_delete` — caused by misregistration of the native method table in the map package.

Common situations: VM development/patches to the map package registration; custom embeddings invoking native map functions directly by name.

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

Appendix: source

Thrown at baml_language/crates/bex_vm/src/package_baml/map.rs:92

        let result: NativeFunctionResult = (|| {
            let key_as_string = vm.as_string(&args[1])?.clone();
            let mut map = vm.as_map_mut(&args[0])?;
            // `shift_remove` preserves the order of remaining entries (matching
            // insertion order) — important since `keys()` / `values()` return
            // entries in insertion order.
            Ok(match map.shift_remove(key_as_string.as_str()) {
                Some(prev) => prev,
                None => Value::NULL,
            })
        })();
        match result {
            Ok(v) => NativeCallResult::Done(v),
            Err(e) => NativeCallResult::Error(e),
        }
    }

    fn delete(_map: &mut IndexMap<BexStr, Value>, _key: &Value) -> Option<Value> {
        unreachable!("Map.delete: should be dispatched via __glue_delete")
    }

    // ── get_or_insert ─────────────────────────────────────────────────────────

    fn __glue_get_or_insert(vm: &mut BexVm, args: &[Value]) -> NativeCallResult {
        let result: NativeFunctionResult = (|| {
            let key_as_string = vm.as_string(&args[1])?.clone();
            let default = args[2];
            let mut map = vm.as_map_mut(&args[0])?;
            Ok(*map.entry(key_as_string).or_insert(default))
        })();
        match result {
            Ok(v) => NativeCallResult::Done(v),
            Err(e) => NativeCallResult::Error(e),
        }
    }

    fn get_or_insert(_map: &mut IndexMap<BexStr, Value>, _key: &Value, _default: &Value) -> Value {

View on GitHub (pinned to bd85ce9dee)