BoundaryML/baml · error · AccessError
Type mismatch: expected
Error message
Type mismatch: expected {expected}, got {actual} What it means
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.
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
Example fix
// before
let s = heap.get_string(value)?; // value is actually an Int
// after
match value {
Value::String(h) => heap.get_string(h)?,
other => return Err(AccessError::TypeMismatch { expected: "String", actual: format!("{:?}", other) }),
} Defensive patterns
Strategy: type-guard
Validate before calling
if !matches!(value, Value::String(_)) {
return Err(AccessError::TypeMismatch { expected: "String", actual: format!("{:?}", value) });
} Type guard
fn is_string(v: &Value) -> bool { matches!(v, Value::String(_)) } Try / catch
match heap.get_string(handle) {
Ok(s) => s,
Err(AccessError::TypeMismatch { expected, actual }) => { log::warn!("wanted {expected}, got {actual}"); coerce_or_default(); },
Err(e) => return Err(e),
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
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
- Field not found: expected
- Function not found
- Invalid handle: expected
- ai.Prompt._data must contain baml_builtins2::PromptAst
- array access on non-list at
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/8bbb552217478b07.
Report an issue: GitHub.
Appendix: source
Thrown at baml_language/crates/bex_heap/src/accessor.rs:18
//! Safe accessor API for external code to read heap objects.
//!
//! External code cannot safely hold bare `HeapPtr` values across GC. This
//! module provides an API that takes a `PermitProof<'_>` (obtained from any
//! held `ActiveHeapPermit<T>`) to witness GC-exclusion at the type level.
use baml_type::RuntimeTy;
use bex_external_types::{BexExternalAdt, BexExternalValue, WeakHeapRef};
use bex_vm_types::{HeapPtr, Object, PermitProof, Value};
use crate::BexHeap;
#[derive(Debug, PartialEq, thiserror::Error, Clone)]
pub enum AccessError {
#[error("Invalid handle: expected {expected}")]
InvalidHandle { expected: &'static str },
#[error("Type mismatch: expected {expected}, got {actual}")]
TypeMismatch {
expected: &'static str,
actual: String,
},
#[error("Field not found: expected {expected}")]
FieldNotFound { expected: String },
#[error("Function not found: {expected}")]
FunctionNotFound { expected: String },
#[error("Cannot convert to owned: {reason}")]
CannotConvertToOwned { reason: String },
}
pub enum BexValue<'a> {
ExternalValue(&'a BexExternalValue),
HeapPtr(&'a HeapPtr),View on GitHub (pinned to bd85ce9dee)