BoundaryML/baml · error · HandleError

handle type mismatch

Error message

handle type mismatch

What it means

HandleError::TypeMismatch from handle.rs. The handle is valid and live, but its handle_type does not match what the operation requires — e.g. passing a runtime handle where a media handle is expected. The bridge checks the type tag on every handle use.

Source

Thrown at baml_language/crates/bridge_cffi/src/handle.rs:21

use std::sync::Arc;

use bex_project::{BexExternalAdt, MediaKind, MediaValue};
use bridge_ctypes::{CffiHandleTableEntry, HANDLE_TABLE, baml_bridge::cffi::BamlHandleType};

/// An owned handle-table key and its protocol type tag.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct HandleParts {
    pub key: u64,
    pub handle_type: i32,
}

/// Failure from a safe ordinary handle or media operation.
#[derive(Clone, Debug, Eq, PartialEq, thiserror::Error)]
pub enum HandleError {
    #[error("invalid handle")]
    InvalidHandle,
    #[error("handle type mismatch")]
    TypeMismatch,
    #[error("unsupported handle type")]
    UnsupportedHandleType,
    #[error("{0}")]
    InvalidInput(String),
}

fn insert_entry(entry: CffiHandleTableEntry) -> HandleParts {
    let handle_type = entry.handle_type() as i32;
    let key = HANDLE_TABLE.insert(entry);
    HandleParts { key, handle_type }
}

fn validate_input(value: &str, field: &str) -> Result<(), HandleError> {
    if value.contains('\0') {
        return Err(HandleError::InvalidInput(format!(
            "{field} contains an embedded NUL byte"
        )));
    }

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Pass the handle kind the API expects — check which create_* call produced it.
  2. Keep handles in distinct, typed variables instead of reusing one.
  3. Check handle_type on the handle struct before the call.
  4. Use strongly typed wrapper bindings rather than raw integers.

Example fix

// before
let h = runtime_handle; // handle_type = RUNTIME
media_read(h);
// after
let h = media_handle;   // handle_type = MEDIA
media_read(h);
Defensive patterns

Strategy: type-guard

Validate before calling

if handle.handle_type != EXPECTED_HANDLE_TYPES['media_read']:
    raise TypeError('wrong handle kind for media_read')

Type guard

def is_media_handle(handle) -> bool:
    return handle.handle_type == HandleType.MEDIA

Try / catch

try:
    result = bridge.media_read(handle)
except BridgeError as e:
    if e is HandleError.TypeMismatch:
        log.error('passed wrong handle kind; check create_* origin')

Prevention

When it happens

Trigger: Passing a handle of the wrong kind to a typed operation (e.g. a function/runtime handle to a media API or vice versa); reusing one handle variable across differently-typed calls; bindings that lose the type distinction and use a single int everywhere.

Common situations: Copy-pasted call code reusing the wrong handle variable; untyped FFI bindings (plain integers) that make cross-typing easy; refactors that changed which object a handle refers to.

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


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