BoundaryML/baml · warning · EngineError

Snapshot not possible for type

Error message

Snapshot not possible for type: {type_name}

What it means

Compiled under the heap_debug feature: the debug snapshot machinery cannot snapshot a value of the given BAML type because no snapshot implementation exists for it. It is a diagnostic/feature-gated limitation, not corruption.

Solutions

  1. Skip snapshotting values of the unsupported type_name and snapshot the rest of the heap
  2. Add a snapshot implementation for that type if it must be captured
  3. Disable heap_debug if snapshots are not needed (also removes this variant)

Example fix

// conceptual
// before
snapshot(value) // panics for Opaque
// after
if snapshot_supported(value) { snapshot(value) } else { skip(value) }
Defensive patterns

Strategy: fallback

Validate before calling

fn snapshotable(v: &BexExternalValue) -> bool {
    !matches!(v, BexExternalValue::Opaque(_))
}

Type guard

fn is_opaque(v: &BexExternalValue) -> bool {
    matches!(v, BexExternalValue::Opaque(_))
}

Try / catch

match snapshot(value) {
    Err(EngineError::CannotSnapshot { type_name }) => {
        eprintln!("skipping {type_name}");
    }
    Ok(s) => store(s),
    Err(e) => handle(e),
}

Prevention

When it happens

Trigger: Invoking heap-debug snapshot APIs while heap_debug is enabled, on a value whose type lacks a snapshot impl (e.g. certain native or opaque objects).

Common situations: Developers debugging VM heap state who snapshot heterogeneous heaps containing unsupported object kinds.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.


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

Appendix: source

Thrown at baml_language/crates/bex_engine/src/lib.rs:852

    /// Clean process-termination request from `baml.sys.exit(code)`.
    /// The caller is expected to honor this as the process exit code.
    /// BAML `int` is `i64`, so the signal carries the full value; the
    /// caller clamps into its shell's range (typically 0..=255 on Unix).
    #[error("baml.sys.exit({code})")]
    Exit { code: i64 },

    #[error("Cannot convert object of type {type_name}")]
    CannotConvert { type_name: String },

    #[error("Type mismatch: {message}")]
    TypeMismatch { message: String },

    #[error("Schema inconsistency: {message}")]
    SchemaInconsistency { message: String },

    #[cfg(feature = "heap_debug")]
    #[error("Snapshot not possible for type: {type_name}")]
    CannotSnapshot { type_name: String },

    #[error("A function call with ID {call_id} is already in progress")]
    DuplicateCallId { call_id: CallId },

    #[error("Package initialization failed: {0}")]
    InitFailed(String),

    #[error("{0}")]
    Other(String),
}

fn format_vm_internal_error(
    err: &bex_vm::errors::VmInternalError,
    trace: &[bex_vm::StackFrame],
) -> String {
    use std::fmt::Write;
    let mut out = bex_vm::format_traceback(

View on GitHub (pinned to bd85ce9dee)