BoundaryML/baml · error · anyhow::Error
Expected a {err_msg}, got: {}
Error message
Expected a {err_msg}, got: {} What it means
This error comes from a macro that implements type-narrowing methods on TypeGeneric<T>. When a method that only makes sense for certain type variants (e.g. primitives, classes) is called on a variant that does not support it (and it is not a recursive type alias that can be expanded), the macro bails with "Expected a <what>, got: <actual>". It signals that the caller assumed the field type had a shape it does not have.
Source
Thrown at engine/baml-lib/baml-types/src/ir_type/mod.rs:101
TypeGeneric::Arrow(_, _) => "function",
TypeGeneric::Union(_, _) => "union",
}
}
}
macro_rules! impl_as_variant {
($method_name:ident, $variant:pat, $err_msg:literal) => {
pub fn $method_name<U: TypeLookupsMeta<T>>(
self,
lookup: &U,
) -> anyhow::Result<TypeGeneric<T>> {
match self {
$variant => Ok(self),
TypeGeneric::RecursiveTypeAlias { name, .. } => {
let expanded_type = TypeLookupsMeta::<T>::expand_recursive_type(lookup, &name)?;
expanded_type.$method_name::<U>(lookup)
}
_ => anyhow::bail!(concat!("Expected a ", $err_msg, ", got: {}"), self),
}
}
};
}
impl<T: MetaSuffix> TypeGeneric<T> {
impl_as_variant!(resolve_map, TypeGeneric::Map(..), "map type");
impl_as_variant!(resolve_list, TypeGeneric::List(..), "list type");
impl_as_variant!(resolve_enum, TypeGeneric::Enum { .. }, "enum type");
impl_as_variant!(resolve_class, TypeGeneric::Class { .. }, "class type");
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, serde::Serialize, strum::Display)]
pub enum StreamingMode {
NonStreaming,
Streaming,
}
View on GitHub (pinned to bd85ce9dee)
Solutions
- Inspect the actual type in the error message and match on the correct TypeGeneric variant before calling the narrowing method.
- Expand recursive type aliases first (expand_recursive_type) so the method can recurse instead of hitting the fallback bail.
- If you control the schema, align the field's declared type with what the calling code expects.
- Use pattern matching (match on TypeGeneric variants) instead of assuming a single variant.
Example fix
// before
let cls = field_type.as_class()?; // panics/bails if field is a union
// after
match field_type {
TypeGeneric::Class(_) => { /* handle class */ }
TypeGeneric::Union(_) => { /* handle union explicitly */ }
_ => anyhow::bail!("unexpected field type"),
} Defensive patterns
Strategy: type-guard
Validate before calling
if !matches!(field_type, TypeGeneric::Class(_) | TypeGeneric::Primitive(_)) { return Err(anyhow!("unexpected variant")); } Type guard
fn is_named_type(t: &TypeGeneric<Meta>) -> bool { matches!(t, TypeGeneric::Class(_) | TypeGeneric::Enum(_)) } Try / catch
match field_type.as_class_if_supported() { Ok(c) => handle(c), Err(e) => log::warn!("type shape mismatch: {}", e) } Prevention
- Match on TypeGeneric variants explicitly instead of assuming one shape
- Expand recursive type aliases before inspection
- Re-run type checks after schema edits
When it happens
Trigger: Calling a TypeGeneric narrowing/inspection method (generated by this macro) on a type whose variant does not match what the method expects, e.g. treating a union, list, or map as a named class, or inspecting a field type before recursive aliases are expanded.
Common situations: BAML schema code or generated clients traversing IR types and assuming a field is e.g. a class or primitive when the schema actually declares a union/list; schema changes that changed a field's type while downstream code assumed the old shape.
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
- exhaustive realized-leaf template classification
- Float literals cannot be parsed
- Could not unify Float with {:?}
- Could not unify Bool with {:?}
- Could not unify map with {field_type:?}
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/28583df6dd17cb96.
Report an issue: GitHub.