BoundaryML/baml · error
Map.set: should be dispatched via __glue_set
Error message
Map.set: should be dispatched via __glue_set
What it means
`Map.set` in the BAML map package is a placeholder that always panics: mutation of maps must go through the `__glue_set` native glue method, which holds the VM borrow needed to write into the map. The direct `set` binding exists only to satisfy the native-function table shape; calling it directly is a dispatch bug.
Solutions
- Fix the dispatch table so `Map.set` resolves to `__glue_set`.
- In BAML code, use map mutation syntax (map[key] = value) rather than any direct native call path.
- Rebuild/upgrade bex_vm if a released build shows this panic.
Example fix
// before "set" => NativeFn::Raw(map::set), // after "set" => NativeFn::Glue(map::__glue_set),
Defensive patterns
Strategy: validation
Validate before calling
// Dispatch-table sanity check at map package registration:
assert!(dispatch_table.get("set") == Some(&NativeFn::Glue(map::__glue_set))); Try / catch
// Panics are not catchable in Rust; verify registration in a startup unit test.
Prevention
- Route all Map mutations through __glue_* native methods.
- Add a registration test asserting each map method maps to its __glue_ implementation.
- Never call raw placeholder native functions directly.
When it happens
Trigger: The VM's method dispatch table routes `Map.set` to the raw `set` function instead of `__glue_set`, typically due to a misregistered native method name in the map package registration code.
Common situations: VM development or patches that alter the map package registration; custom glue dispatch layers that call native functions by name without applying the __glue_ prefix rules.
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
- Map.delete: should be dispatched via __glue_delete
- Map.get_or_insert: should be dispatched via…
- ai.Prompt._data must contain baml_builtins2::PromptAst
- ai.Prompt.messages receiver must be an ai.Prompt instance
- array access should be either map or array.
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/920618c6ea07211d.
Report an issue: GitHub.
Appendix: source
Thrown at baml_language/crates/bex_vm/src/package_baml/map.rs:60
let result: NativeFunctionResult = (|| {
let key_as_string = vm.as_string(&args[1])?.clone();
let value = args[2];
let mut map = vm.as_map_mut(&args[0])?;
// `IndexMap::insert` returns `Some(prev)` if the key already
// existed, `None` otherwise — exactly the V? semantics we want.
Ok(match map.insert(key_as_string, value) {
Some(prev) => prev,
None => Value::NULL,
})
})();
match result {
Ok(v) => NativeCallResult::Done(v),
Err(e) => NativeCallResult::Error(e),
}
}
fn set(_map: &mut IndexMap<BexStr, Value>, _key: &Value, _value: &Value) -> Option<Value> {
unreachable!("Map.set: should be dispatched via __glue_set")
}
fn get(vm: &BexVm, map: MapView<'_>, key: &Value) -> Option<Value> {
if let Ok(k) = vm.as_string(key) {
map.get(k.as_str()).copied()
} else {
None
}
}
// ── delete ────────────────────────────────────────────────────────────────
fn __glue_delete(vm: &mut BexVm, args: &[Value]) -> NativeCallResult {
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()` returnView on GitHub (pinned to bd85ce9dee)