BoundaryML/baml · error · EngineError

Cannot convert object of type

Error message

Cannot convert object of type {type_name}

What it means

The engine was asked to convert a BAML object into a host/external representation but the object's type has no conversion defined. The message names the offending BAML type (type_name). It indicates a mismatch between what the host expects and what the VM produced.

Solutions

  1. Return a convertible type (primitive, list, map) from the BAML function instead of the custom object
  2. Convert the object to a plain representation inside BAML before returning
  3. Check type_name and add/extend conversion support in the host integration
  4. Upgrade the engine — newer versions may support converting this type

Example fix

// before (BAML)
function f() { return MyClass(...) } // object not convertible
// after
function f() { return MyClass(...).to_dict() } // or return fields individually
Defensive patterns

Strategy: type-guard

Validate before calling

fn convertible(v: &BexExternalValue) -> bool {
    matches!(v, BexExternalValue::Null(_) | BexExternalValue::Int(_) | BexExternalValue::String(_) | BexExternalValue::List(_) | BexExternalValue::Map(_))
}

Type guard

fn is_plain_value(v: &BexExternalValue) -> bool {
    !matches!(v, BexExternalValue::Object(o) if o.is_class_instance())
}

Prevention

When it happens

Trigger: Calling APIs that export BAML values to the host (e.g. serialization/conversion entry points) with an object type lacking a converter — e.g. passing a class instance or opaque object where only primitives/maps are supported.

Common situations: Returning custom class instances from BAML functions to a host that expects JSON-able values; version changes adding new value kinds before converters exist.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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

Appendix: source

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

        source: bex_vm::errors::VmInternalError,
        trace: Vec<bex_vm::StackFrame>,
    },

    /// Either a BAML panic or a BAML error value.
    #[error("{}", format_unhandled_throw(value, trace))]
    UnhandledThrow {
        value: Box<BexExternalValue>,
        trace: Vec<bex_vm::StackFrame>,
    },

    /// 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),

View on GitHub (pinned to bd85ce9dee)