BoundaryML/baml · error · VmPanic

baml.panics.HostContractViolation

baml.panics.HostContractViolation

Error message

host contract violation: {message} [class={class_name:?}, lang={language:?}]

What it means

This panic surfaces when a host callable violates its contract: either it returned a value of the wrong type, or it threw a value that does not match its declared `throws` contract `E`. It maps to `baml.panics.HostContractViolation` in BAML. The `class_name` and `language` fields echo the offending host exception's identity when the violation came from a host throw, and are `None` for wrong-type returns.

Source

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

    /// fall back gracefully instead of aborting the host process.
    #[error("host resource '{resource}' unavailable: {message}")]
    HostUnavailable { resource: String, message: String },

    /// The right operand of a bigint shift (`<<` / `>>`) was negative.
    /// Catchable because the count is a runtime `bigint` and the type
    /// system can't rule out negative values.
    #[error("negative bit shift: {message}")]
    NegativeBitShift { message: String },

    /// A host callable returned a value of the wrong type, or threw a value
    /// that does not match its declared `throws` contract `E`. Surfaces in
    /// BAML as `baml.panics.HostContractViolation`.
    ///
    /// `class_name` / `language` are populated when the violation arose from
    /// a host throw (echoing the offending host exception's identity) and
    /// `None` when it arose from a wrong-type return (no exception class to
    /// echo).
    #[error("host contract violation: {message} [class={class_name:?}, lang={language:?}]")]
    HostContractViolation {
        message: String,
        class_name: Option<String>,
        language: Option<String>,
    },
}

/// An error value from the BAML standard library. Maps 1:1 to a `baml.errors.*` class.
#[derive(Debug, Error, PartialEq, Clone)]
pub enum VmBamlError {
    #[error("invalid argument: {message}")]
    InvalidArgument { message: String },

    #[error("parse error: {message}")]
    ParseError { message: String },

    #[error("I/O error: {message}")]
    Io { message: String },

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Update the host function's declared signature/`throws` contract to match what it actually returns/throws.
  2. Fix the host implementation to return the declared type and throw only values of the declared error type `E`.
  3. Inspect the message's `[class=..., lang=...]` fields to identify exactly which host exception class and language caused the mismatch.
  4. Re-run integration tests covering the host-callable boundary after any binding changes.

Example fix

// before (host)
function parseConfig(s) { throw new Error("bad"); } // undeclared throw type
// after (host)
// declare the contract so thrown values match E, or return a typed result
function parseConfig(s): Result<Config, ParseError> {
  try { return ok(parse(s)); } catch (e) { return err(new ParseError(e.message)); }
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Host (TS): assert the return matches the declared contract
if (typeof result !== "string") throw new TypeError("host fn must return string");

Type guard

// TS: narrow host results to the declared type before returning
function isConfig(v: unknown): v is Config {
  return typeof v === "object" && v !== null && "name" in v;
}

Try / catch

try {
  let r = host.call();
} catch e: baml.panics.HostContractViolation {
  log("violation class=" + e.class_name + " lang=" + e.language);
  return default_result();
}

Prevention

When it happens

Trigger: A host function (registered from e.g. Python/TypeScript) returns a value whose type does not match the signature the VM expects, or throws an exception object inconsistent with its declared throws type — detected at the VM boundary when marshaling the result or exception.

Common situations: Changing a host function's return type (or throwing a custom exception class) after registering it without updating its declared contract; host code throwing raw values (strings/numbers) instead of the declared error type; multi-language bindings where the Python/TS side drifted from the BAML-side declaration.

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