BoundaryML/baml · error · VmBamlError

host callable error: {message} [class={class_name}, lang={la

Error message

host callable error: {message} [class={class_name}, lang={language:?}]

What it means

This is the HostCallable variant of the VM error enum: an error value that originated in the host language (Python, TypeScript, Ruby, etc.) when calling into a host callable from BAML. It carries class_name, message, optional traceback and language, plus a handle referencing the original host exception object in the process-global host-value table so the host runtime can rehydrate the real exception. Engine-side faults with no underlying host exception must NOT use this variant — those route through VmInternalError::BridgeFailure.

Source

Thrown at baml_language/crates/bex_vm_types/src/errors.rs:157

    /// An error value from the host language that has no direct BAML
    /// representation. The `handle` is the load-bearing field — it
    /// references the original host exception object via the
    /// process-global host-value table, so the originating runtime can
    /// recover the exact native exception on round-trip. The
    /// `class_name` / `message` / `language` / `traceback` fields are
    /// purely metadata for debugging, logging, and user-facing
    /// formatting — they do not participate in error matching or
    /// rehydration.
    ///
    /// Surfaces in BAML as a `baml.errors.HostCallable` Instance whose
    /// `_handle` field is materialized from `handle`. Engine-side
    /// failures with no underlying host exception (bridge serialization
    /// faults, missing-bridge errors, etc.) MUST use a different
    /// variant — they are not host-language errors and have nothing to
    /// rehydrate. Such SDK/bridge faults route through fatal
    /// [`VmInternalError::BridgeFailure`].
    #[error("host callable error: {message} [class={class_name}, lang={language:?}]")]
    HostCallable {
        class_name: String,
        message: String,
        traceback: Option<String>,
        language: Option<String>,
        /// Required: handle to the originating host exception object
        /// (registered in the per-bridge host-value table at the point
        /// of the throw). Materialized into the BAML class's `_handle`
        /// field on the way out so the originating runtime can resolve
        /// it back to the original native exception.
        handle: std::sync::Arc<bex_resource_types::HostValueArc>,
    },
}

impl VmBamlError {
    /// Map this `baml.errors.*` value to its contract-level
    /// [`SysOpErrorCategory`] — the finite set of categories that sysop
    /// `#[throws(...)]` annotations reference.

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Inspect class_name/message/traceback to identify the host exception, and fix the bug in the host function itself.
  2. On the host side, catch the exception at the callable boundary if it should be handled inside BAML instead of propagating.
  3. Use the handle to rehydrate the original exception in the host runtime for full stack details.
  4. Ensure the bridge/SDK versions match between host language and BAML runtime.

Example fix

# before: host callable raises -> host callable error: bad input [class=ValueError, lang=Python]
def my_tool(x):
    return int(x)  # throws on bad input

# after: validate at the boundary
def my_tool(x):
    try:
        return int(x)
    except ValueError:
        return "invalid input"
Defensive patterns

Strategy: try-catch

Validate before calling

# Host side (Python): wrap callables that may throw
def safe_tool(fn):
    def wrapper(*a, **kw):
        try:
            return fn(*a, **kw)
        except Exception as e:
            return {"__tool_error__": type(e).__name__, "msg": str(e)}
    return wrapper

Try / catch

match vm_result {
    Err(BexError::HostCallable { class_name, message, traceback, handle, .. }) => {
        let host_exc = rehydrate_exception(handle)?;
        eprintln!("host error {}: {}\n{:?}", class_name, message, traceback);
    }
    other => other?,
}

Prevention

When it happens

Trigger: A host function/class method invoked from BAML raised an exception; the bridge captured the host exception (e.g. a Python ValueError or JS TypeError) and serialized it into this VM error, keeping a handle to the original object.

Common situations: BAML calling a custom tool/function written in Python or TS that throws; host-side dependency failures (network libs, file IO) surfacing inside BAML execution; version mismatches between host SDK and BAML runtime altering callable behavior.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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