BoundaryML/baml · error · anyhow::Error
Unification error
Error message
Unification error
What it means
In `BamlValueWithMeta::zip_meta`, which zips two meta-annotated BAML values shape-by-shape, a `String`-vs-non-`String` pair falls into the catch-all arm `(String(_,_), _) => anyhow::bail!("Unification error")`. It means the two values being unified have different BAML types at this position, so they cannot be zipped into a single value with paired metadata.
Source
Thrown at engine/baml-lib/baml-types/src/baml_value.rs:1244
/// The baml value calling `zip_meta` is the "primary" one, whose value
/// data will live on in the returned baml value.
pub fn zip_meta<U: Clone + std::fmt::Debug>(
self,
other: &BamlValueWithMeta<U>,
) -> Result<BamlValueWithMeta<(T, U)>>
where
T: std::fmt::Debug,
{
let other_meta: U = other.meta().clone();
let error_msg = String::new();
let ret = match (self, other) {
(BamlValueWithMeta::Null(meta1), _) => {
Result::<_, _>::Ok(BamlValueWithMeta::Null((meta1, other_meta)))
}
(BamlValueWithMeta::String(s1, meta1), BamlValueWithMeta::String(_s2, _)) if true => {
Ok(BamlValueWithMeta::String(s1, (meta1, other_meta)))
}
(BamlValueWithMeta::String(_, _), _) => anyhow::bail!("Unification error"),
(BamlValueWithMeta::Int(s1, meta1), BamlValueWithMeta::Int(_s2, _)) if true => {
Ok(BamlValueWithMeta::Int(s1, (meta1, other_meta)))
}
(BamlValueWithMeta::Int(_, _), _) => anyhow::bail!("Unification error"),
(BamlValueWithMeta::Float(s1, meta1), BamlValueWithMeta::Float(_s2, _)) if true => {
Ok(BamlValueWithMeta::Float(s1, (meta1, other_meta)))
}
(BamlValueWithMeta::Float(_, _), _) => anyhow::bail!("Unification error"),
(BamlValueWithMeta::Bool(s1, meta1), BamlValueWithMeta::Bool(_s2, _)) if true => {
Ok(BamlValueWithMeta::Bool(s1, (meta1, other_meta)))
}
(BamlValueWithMeta::Bool(_, _), _) => anyhow::bail!("Unification error"),
(BamlValueWithMeta::Map(s1, meta1), BamlValueWithMeta::Map(s2, _)) => {
let map_result = s1
.into_iter()
.zip(s2)
.map(|((k1, v1), (_k2, v2))| v1.zip_meta(v2).map(|res| (k1, res)))
.collect::<Result<IndexMap<_, _>>>()?;View on GitHub (pinned to bd85ce9dee)
Solutions
- Verify both values' types before calling zip_meta; only zip values of the same BAML type.
- Check where the two values diverge — typically one came from a parse of model output and the other from a schema/coercion step.
- If a String-vs-other unification is legitimately expected, convert one side explicitly first (e.g. parse or wrap).
- Capture the enclosing error_msg: zip_meta maps any failure to it, so the underlying bail is reported via that message.
Example fix
// before
let zipped = string_value.zip_meta(other_value)?; // Unification error
// after
if matches!(other_value, BamlValueWithMeta::String(..)) {
let zipped = string_value.zip_meta(other_value)?;
} else {
return Err(anyhow!("expected string value, got different BAML type"));
} Defensive patterns
Strategy: type-guard
Validate before calling
// Rust: verify both values are String-typed before zip_meta
fn can_zip_strings(a: &BamlValueWithMeta<M1, M2>, b: &BamlValueWithMeta<M1, M2>) -> bool {
matches!(a, BamlValueWithMeta::String(..)) && matches!(b, BamlValueWithMeta::String(..))
} Type guard
fn as_string(v: &BamlValueWithMeta<M1, M2>) -> Option<(&str,)> {
if let BamlValueWithMeta::String(s, _) = v { Some((s,)) } else { None }
} Try / catch
// Rust
match a.zip_meta(b) {
Ok(zipped) => use(zipped),
Err(e) if e.to_string().contains("Unification error") => {
// shapes diverged: log both value types and fall back to per-type handling
}
Err(e) => return Err(e),
} Prevention
- Always derive both operands from the same parse/coercion pipeline so shapes match
- Add a shape pre-check (same variant) before any zip_meta call
- When model output may be prose, coerce to the expected type before unifying
- Wrap zip_meta in a helper that returns a descriptive type-mismatch error instead of the bare 'Unification error'
When it happens
Trigger: Calling `value_a.zip_meta(value_b)` (public API) where value_a is a BamlValueWithMeta::String and value_b is Null, Int, Float, Bool, Map, List, Media, Enum, or Class.
Common situations: Comparing/streaming partial LLM output against an expected value where the model returned a string but the target value is a different type (or vice versa); merging results of two BAML runs whose shapes diverged.
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
- Could not unify String with {:?}
- Could not unify Int with {:?}
- Could not unify Float with {:?}
- Could not unify Bool with {:?}
- Expected a string, not an array
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/05a2f7f690e4fc10.
Report an issue: GitHub.