{"record":{"id":"2bdbd8328fae2779","repo":"BoundaryML/baml","slug":"baml-panics-hostcontractviolation","errorCode":"baml.panics.HostContractViolation","errorMessage":"host contract violation: {message} [class={class_name:?}, lang={language:?}]","messagePattern":"host contract violation: (.+?) \\[class=(.+?), lang=(.+?)\\]","errorType":"error_code","errorClass":"VmPanic","httpStatus":null,"severity":"error","filePath":"baml_language/crates/bex_vm_types/src/errors.rs","lineNumber":102,"sourceCode":"    /// fall back gracefully instead of aborting the host process.\n    #[error(\"host resource '{resource}' unavailable: {message}\")]\n    HostUnavailable { resource: String, message: String },\n\n    /// The right operand of a bigint shift (`<<` / `>>`) was negative.\n    /// Catchable because the count is a runtime `bigint` and the type\n    /// system can't rule out negative values.\n    #[error(\"negative bit shift: {message}\")]\n    NegativeBitShift { message: String },\n\n    /// A host callable returned a value of the wrong type, or threw a value\n    /// that does not match its declared `throws` contract `E`. Surfaces in\n    /// BAML as `baml.panics.HostContractViolation`.\n    ///\n    /// `class_name` / `language` are populated when the violation arose from\n    /// a host throw (echoing the offending host exception's identity) and\n    /// `None` when it arose from a wrong-type return (no exception class to\n    /// echo).\n    #[error(\"host contract violation: {message} [class={class_name:?}, lang={language:?}]\")]\n    HostContractViolation {\n        message: String,\n        class_name: Option<String>,\n        language: Option<String>,\n    },\n}\n\n/// An error value from the BAML standard library. Maps 1:1 to a `baml.errors.*` class.\n#[derive(Debug, Error, PartialEq, Clone)]\npub enum VmBamlError {\n    #[error(\"invalid argument: {message}\")]\n    InvalidArgument { message: String },\n\n    #[error(\"parse error: {message}\")]\n    ParseError { message: String },\n\n    #[error(\"I/O error: {message}\")]\n    Io { message: String },","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/baml_language/crates/bex_vm_types/src/errors.rs#L84-L120","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Update the host function's declared signature/`throws` contract to match what it actually returns/throws.","Fix the host implementation to return the declared type and throw only values of the declared error type `E`.","Inspect the message's `[class=..., lang=...]` fields to identify exactly which host exception class and language caused the mismatch.","Re-run integration tests covering the host-callable boundary after any binding changes."],"exampleFix":"// before (host)\nfunction parseConfig(s) { throw new Error(\"bad\"); } // undeclared throw type\n// after (host)\n// declare the contract so thrown values match E, or return a typed result\nfunction parseConfig(s): Result<Config, ParseError> {\n  try { return ok(parse(s)); } catch (e) { return err(new ParseError(e.message)); }\n}","handlingStrategy":"type-guard","validationCode":"// Host (TS): assert the return matches the declared contract\nif (typeof result !== \"string\") throw new TypeError(\"host fn must return string\");","typeGuard":"// TS: narrow host results to the declared type before returning\nfunction isConfig(v: unknown): v is Config {\n  return typeof v === \"object\" && v !== null && \"name\" in v;\n}","tryCatchPattern":"try {\n  let r = host.call();\n} catch e: baml.panics.HostContractViolation {\n  log(\"violation class=\" + e.class_name + \" lang=\" + e.language);\n  return default_result();\n}","preventionTips":["Keep host function implementations and their declared BAML contracts in sync.","Only throw values of the declared error type E from host callables.","Add boundary tests for every host-registered function.","When changing a host function's signature, update the BAML-side declaration in the same change."],"tags":["host-boundary","ffi","contract-violation","type-mismatch","catchable"],"backgroundTag":"type-mismatch","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}