BoundaryML/baml · error

Expected TypeBuilder, got {}

Error message

Expected TypeBuilder, got {}

What it means

Thrown while decoding BamlFunctionArguments when the optional type_builder field decodes to a RawPtrType that is not a TypeBuilder. The message names the actual variant found, indicating the host passed a pointer to a different kind of object.

Source

Thrown at engine/language_client_cffi/src/ctypes/function_args_decode.rs:59

                .map(|r| match r {
                    Ok(RawPtrType::Collector(c)) => Ok(c),
                    Err(e) => Err(e),
                    Ok(other) => Err(anyhow::anyhow!("Expected Collector, got {}", other.name())),
                })
                .collect::<Result<Vec<_>, _>>()?;
            if collectors.is_empty() {
                None
            } else {
                Some(collectors)
            }
        };
        let type_builder = from
            .type_builder
            .map(RawPtrType::decode)
            .transpose()?
            .map(|r| match r {
                RawPtrType::TypeBuilder(t) => Ok(t),
                other => Err(anyhow::anyhow!(
                    "Expected TypeBuilder, got {}",
                    other.name()
                )),
            })
            .transpose()?;

        let tags = from
            .tags
            .into_iter()
            .map(|v| {
                from_host_kv_to_baml_kv(v).and_then(|(k, v)| match v {
                    BamlValue::String(s) => Ok((k, s)),
                    _ => anyhow::bail!("Expected string value for tag key {}", k),
                })
            })
            .collect::<Result<_, _>>()?;

        Ok(BamlFunctionArguments {

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Ensure the object passed as type_builder was created with the client's TypeBuilder API
  2. Rebuild/reacquire the TypeBuilder handle if the runtime may have recycled it, and avoid caching handles across client restarts
  3. Upgrade the host bindings and engine together so RawPtrType variants stay in sync

Example fix

// before (host pseudocode)
args.type_builder = collector

// after
tb = client.create_type_builder()
args.type_builder = tb
Defensive patterns

Strategy: type-guard

Validate before calling

# host side
if type_builder is not None and not isinstance(type_builder, TypeBuilder):
    raise TypeError(f"type_builder must be a TypeBuilder, got {type(type_builder).__name__}")

Type guard

function isTypeBuilder(obj) { return obj && obj.__baml_type === 'TypeBuilder'; }

Try / catch

try:
    result = client.CallFunction(fn, args)
except Exception as e:
    if "Expected TypeBuilder" in str(e):
        raise TypeError("The type_builder argument must be a TypeBuilder instance") from e
    raise

Prevention

When it happens

Trigger: Passing an object other than a TypeBuilder (e.g. a Collector or client pointer) in the type_builder argument of a BAML function call, or a stale registry handle decoding to the wrong variant.

Common situations: Swapped variables in host code, reusing cached object handles after the registry was rebuilt, or SDK/engine version mismatch changing pointer variant ordering.

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/ab2704b7edfb8384. Report an issue: GitHub.