BoundaryML/baml · error
Expected string value for tag key {}
Error message
Expected string value for tag key {} What it means
Thrown while decoding the tags field of BamlFunctionArguments: each tag entry is decoded via from_host_kv_to_baml_kv and must carry a BamlValue::String. If the decoded value is any other BamlValue variant (int, bool, map, etc.), the decode fails naming the offending tag key.
Source
Thrown at engine/language_client_cffi/src/ctypes/function_args_decode.rs:72
.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 {
kwargs,
client_registry,
env_vars,
collectors,
type_builder,
tags,
})
}
}
impl Decode for ClientRegistry {
type From = crate::baml::cffi::HostClientRegistry;
View on GitHub (pinned to bd85ce9dee)
Solutions
- Convert all tag values to strings on the host side before passing them (e.g. str(value) or String(value))
- If richer values are needed, flatten them into multiple string tags (e.g. "attempt": "3")
- Add a host-side validator for the tags map that rejects non-string values with a clearer message
Example fix
// before (Python)
tags = {"attempt": 3}
// after
tags = {"attempt": str(3)} # or "3" Defensive patterns
Strategy: validation
Validate before calling
def validate_tags(tags):
bad = {k: type(v).__name__ for k, v in tags.items() if not isinstance(v, str)}
if bad:
raise TypeError(f"Tag values must be strings, fix: {bad}")
return {k: str(v) for k, v in tags.items()}
tags = validate_tags(tags) Type guard
def all_string_values(d: dict) -> bool:
return all(isinstance(v, str) for v in d.values()) Try / catch
try:
result = client.CallFunction(fn, args)
except Exception as e:
if "Expected string value for tag key" in str(e):
raise TypeError("Coerce tag values to strings, e.g. {'attempt': '3'}") from e
raise Prevention
- Treat tags as a string-to-string map by convention
- Coerce numeric/boolean tag values with str() at call sites
- Validate tags once in a shared helper used by all BAML invocations
When it happens
Trigger: Passing non-string tag values (numbers, booleans, objects) in the tags argument of a BAML function call, e.g. tags={"attempt": 3} instead of {"attempt": "3"}.
Common situations: Developers attaching observability/metadata tags with natural numeric or boolean values, or templating that substitutes unquoted values into tag maps.
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
- Expected Collector, got {}
- Expected TypeBuilder, got {}
- Key is missing
- Value is null for key {}
- Key must be a string
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/2f1751c7737516c0.
Report an issue: GitHub.