{"record":{"id":"1567d11d15479ac6","repo":"BoundaryML/baml","slug":"host-callable-error-message-class-class-name-lang-language","errorCode":null,"errorMessage":"host callable error: {message} [class={class_name}, lang={language:?}]","messagePattern":"host callable error: (.+?) \\[class=(.+?), lang=(.+?)\\]","errorType":"exception","errorClass":"VmBamlError","httpStatus":null,"severity":"error","filePath":"baml_language/crates/bex_vm_types/src/errors.rs","lineNumber":157,"sourceCode":"\n    /// An error value from the host language that has no direct BAML\n    /// representation. The `handle` is the load-bearing field — it\n    /// references the original host exception object via the\n    /// process-global host-value table, so the originating runtime can\n    /// recover the exact native exception on round-trip. The\n    /// `class_name` / `message` / `language` / `traceback` fields are\n    /// purely metadata for debugging, logging, and user-facing\n    /// formatting — they do not participate in error matching or\n    /// rehydration.\n    ///\n    /// Surfaces in BAML as a `baml.errors.HostCallable` Instance whose\n    /// `_handle` field is materialized from `handle`. Engine-side\n    /// failures with no underlying host exception (bridge serialization\n    /// faults, missing-bridge errors, etc.) MUST use a different\n    /// variant — they are not host-language errors and have nothing to\n    /// rehydrate. Such SDK/bridge faults route through fatal\n    /// [`VmInternalError::BridgeFailure`].\n    #[error(\"host callable error: {message} [class={class_name}, lang={language:?}]\")]\n    HostCallable {\n        class_name: String,\n        message: String,\n        traceback: Option<String>,\n        language: Option<String>,\n        /// Required: handle to the originating host exception object\n        /// (registered in the per-bridge host-value table at the point\n        /// of the throw). Materialized into the BAML class's `_handle`\n        /// field on the way out so the originating runtime can resolve\n        /// it back to the original native exception.\n        handle: std::sync::Arc<bex_resource_types::HostValueArc>,\n    },\n}\n\nimpl VmBamlError {\n    /// Map this `baml.errors.*` value to its contract-level\n    /// [`SysOpErrorCategory`] — the finite set of categories that sysop\n    /// `#[throws(...)]` annotations reference.","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/baml_language/crates/bex_vm_types/src/errors.rs#L139-L175","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect class_name/message/traceback to identify the host exception, and fix the bug in the host function itself.","On the host side, catch the exception at the callable boundary if it should be handled inside BAML instead of propagating.","Use the handle to rehydrate the original exception in the host runtime for full stack details.","Ensure the bridge/SDK versions match between host language and BAML runtime."],"exampleFix":"# before: host callable raises -> host callable error: bad input [class=ValueError, lang=Python]\ndef my_tool(x):\n    return int(x)  # throws on bad input\n\n# after: validate at the boundary\ndef my_tool(x):\n    try:\n        return int(x)\n    except ValueError:\n        return \"invalid input\"","handlingStrategy":"try-catch","validationCode":"# Host side (Python): wrap callables that may throw\ndef safe_tool(fn):\n    def wrapper(*a, **kw):\n        try:\n            return fn(*a, **kw)\n        except Exception as e:\n            return {\"__tool_error__\": type(e).__name__, \"msg\": str(e)}\n    return wrapper","typeGuard":null,"tryCatchPattern":"match vm_result {\n    Err(BexError::HostCallable { class_name, message, traceback, handle, .. }) => {\n        let host_exc = rehydrate_exception(handle)?;\n        eprintln!(\"host error {}: {}\\n{:?}\", class_name, message, traceback);\n    }\n    other => other?,\n}","preventionTips":["Validate inputs inside host callables before doing work.","Catch expected exceptions at the callable boundary in the host language.","Keep bridge/SDK versions in sync between host runtime and BAML.","Distinguish host exceptions from bridge faults (bridge faults use VmInternalError::BridgeFailure)."],"tags":["baml","host-language","bridge","exception"],"backgroundTag":"type-mismatch","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}