{"record":{"id":"8bbb552217478b07","repo":"BoundaryML/baml","slug":"type-mismatch-expected-expected-got-actual","errorCode":null,"errorMessage":"Type mismatch: expected {expected}, got {actual}","messagePattern":"Type mismatch: expected (.+?), got (.+?)","errorType":"exception","errorClass":"AccessError","httpStatus":null,"severity":"error","filePath":"baml_language/crates/bex_heap/src/accessor.rs","lineNumber":18,"sourceCode":"//! Safe accessor API for external code to read heap objects.\n//!\n//! External code cannot safely hold bare `HeapPtr` values across GC. This\n//! module provides an API that takes a `PermitProof<'_>` (obtained from any\n//! held `ActiveHeapPermit<T>`) to witness GC-exclusion at the type level.\n\nuse baml_type::RuntimeTy;\nuse bex_external_types::{BexExternalAdt, BexExternalValue, WeakHeapRef};\nuse bex_vm_types::{HeapPtr, Object, PermitProof, Value};\n\nuse crate::BexHeap;\n\n#[derive(Debug, PartialEq, thiserror::Error, Clone)]\npub enum AccessError {\n    #[error(\"Invalid handle: expected {expected}\")]\n    InvalidHandle { expected: &'static str },\n\n    #[error(\"Type mismatch: expected {expected}, got {actual}\")]\n    TypeMismatch {\n        expected: &'static str,\n        actual: String,\n    },\n\n    #[error(\"Field not found: expected {expected}\")]\n    FieldNotFound { expected: String },\n\n    #[error(\"Function not found: {expected}\")]\n    FunctionNotFound { expected: String },\n\n    #[error(\"Cannot convert to owned: {reason}\")]\n    CannotConvertToOwned { reason: String },\n}\n\npub enum BexValue<'a> {\n    ExternalValue(&'a BexExternalValue),\n    HeapPtr(&'a HeapPtr),","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/baml_language/crates/bex_heap/src/accessor.rs#L1-L36","documentation":"AccessError::TypeMismatch is returned by bex_heap accessors when a handle points to a live object but of the wrong type for the requested operation — e.g. reading a struct field from an object that is actually a list. `expected` names the required type and `actual` carries the debug representation of what was found.","triggerScenarios":"Calling a typed accessor (get_string, get_field, call_function, etc.) with a Value/HeapPtr whose runtime type differs from the accessor's expectation, often after an unchecked downcast.","commonSituations":"Script values flowing into native code with assumed types; schema changes to object layouts; skipping the type check branch of a match on Value and falling through to a typed accessor.","solutions":["Match on the Value/Object variant and handle each type explicitly before calling typed accessors","Use type-checking helpers on the heap before narrowing","Fix the producer of the value so the correct type is stored","Log `actual` from the error to find where the wrong-typed value originated"],"exampleFix":"// before\nlet s = heap.get_string(value)?; // value is actually an Int\n// after\nmatch value {\n    Value::String(h) => heap.get_string(h)?,\n    other => return Err(AccessError::TypeMismatch { expected: \"String\", actual: format!(\"{:?}\", other) }),\n}","handlingStrategy":"type-guard","validationCode":"if !matches!(value, Value::String(_)) {\n    return Err(AccessError::TypeMismatch { expected: \"String\", actual: format!(\"{:?}\", value) });\n}","typeGuard":"fn is_string(v: &Value) -> bool { matches!(v, Value::String(_)) }","tryCatchPattern":"match heap.get_string(handle) {\n    Ok(s) => s,\n    Err(AccessError::TypeMismatch { expected, actual }) => { log::warn!(\"wanted {expected}, got {actual}\"); coerce_or_default(); },\n    Err(e) => return Err(e),\n}","preventionTips":["Match exhaustively on Value variants before typed accessors","Keep native<->script boundaries typed with explicit conversion helpers","Log the `actual` payload to trace where wrong-typed values originate"],"tags":["type-mismatch","heap","vm"],"backgroundTag":"type-mismatch","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}