BoundaryML/baml · error

Future short-circuited above

Error message

Future short-circuited above

What it means

A defensive `unreachable!` in deep_copy_value_recursive: `Object::Future` values are supposed to be short-circuited earlier in the deep-copy routine and never reach this match arm. Hitting it means the pre-match short-circuit logic failed to intercept a Future.

Solutions

  1. Avoid deep-copying values that contain pending Futures; resolve/await them first.
  2. Update to the latest VM version where Future handling in deep_copy may be fixed.
  3. Report to maintainers — the short-circuit invariant was violated.
Defensive patterns

Strategy: validation

Validate before calling

// avoid deep-copying values containing futures
function containsFuture(v) { return v && (v.type === 'Future' || (Array.isArray(v) && v.some(containsFuture))); }

Type guard

function isCopyable(v) { return v == null || v.type !== 'Future'; }

Prevention

When it happens

Trigger: Calling deep_copy on a value graph containing a Future whose representation reaches the recursive match without being caught by the earlier Future short-circuit branch (e.g. a Future wrapped in an unhandled container or an unscheduled/derived Future variant).

Common situations: Deep-copying structures that hold futures (async results stored in objects/arrays); VM changes that introduce new Future-like variants without updating the short-circuit; VM bugs.

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

Appendix: source

Thrown at baml_language/crates/bex_vm/src/package_baml/root.rs:882

                    // no GC write barrier because it is all in gen0
                    *vm.get_object_mut(placeholder_ptr) = Object::Instance(new_instance);
                    placeholder_ptr
                }

                // Bigint is behind Arc — clone() is cheap (increments refcount).
                Object::Bigint(arc) => vm.tlab.alloc(Object::Bigint(std::sync::Arc::clone(&arc))),
                Object::Function(f) => vm.tlab.alloc(Object::Function(f)),
                Object::Interface(i) => vm.tlab.alloc(Object::Interface(i)),
                Object::Package(p) => vm.tlab.alloc(Object::Package(p)),
                Object::ImplRule(r) => vm.tlab.alloc(Object::ImplRule(r)),
                Object::Class(c) => vm.tlab.alloc(Object::Class(c)),
                Object::Enum(e) => vm.tlab.alloc(Object::Enum(e)),
                Object::TypeAlias(a) => vm.tlab.alloc(Object::TypeAlias(a)),
                Object::Variant(v) => vm.tlab.alloc(Object::Variant(v)),
                Object::RustData(arc) => vm.tlab.alloc(Object::RustData(Arc::clone(&arc))),
                // `Object::Future(_)` is short-circuited above; it can't
                // reach this match arm.
                Object::Future(_) => unreachable!("Future short-circuited above"),
                Object::UnscheduledFuture(f) => vm.tlab.alloc(Object::UnscheduledFuture(f)),
                // A deep copy denotes the same type: clone the `TypeValue`
                // whole, definition overlay and owner edge included.
                Object::Type(ty) => vm.tlab.alloc(Object::Type(ty)),
                // Closures, bound methods, and cells are shallow-copied: the captured
                // state is shared by design (mutation semantics).
                Object::Closure(c) => vm.tlab.alloc(Object::Closure(c)),
                Object::BoundMethod(bm) => vm.tlab.alloc(Object::BoundMethod(bm)),
                Object::GenericFunction(gf) => vm.tlab.alloc(Object::GenericFunction(gf)),
                // `HostClosure` is a value-type wrapper around an
                // `Arc<HostValueArc>`; cloning the Arc is cheap and matches
                // the closure semantics (shared handle).
                Object::HostClosure(hc) => vm.tlab.alloc(Object::HostClosure(hc)),
                Object::Cell(cell) => vm.tlab.alloc(Object::Cell(cell)),
                #[cfg(feature = "heap_debug")]
                Object::Sentinel(kind) => vm.tlab.alloc(Object::Sentinel(kind)),
            };

View on GitHub (pinned to bd85ce9dee)