BoundaryML/baml · error
Key must be a string
Error message
Key must be a string
What it means
Thrown by from_host_map_entry when a HostMapEntry's key oneof is not StringKey (it is IntKey, BoolKey, EnumKey, or unset). The plain CFFI Value decoder only supports string keys, so any other key type is rejected with this fixed message.
Source
Thrown at engine/language_client_cffi/src/ctypes/cffi_value_decode.rs:54
.map(from_host_map_entry)
.collect::<Result<_, _>>()?;
Value::Class(c.name, fields, ())
}
HostVal::EnumValue(e) => Value::Enum(e.name, e.value, ()),
HostVal::Handle(handle) => {
let raw_ptr = RawPtrType::decode(handle)?;
Value::RawPtr(raw_ptr, ())
}
})
}
}
pub(super) fn from_host_map_entry(
item: crate::baml::cffi::HostMapEntry,
) -> Result<(String, Value), anyhow::Error> {
let key = match item.key {
Some(crate::baml::cffi::host_map_entry::Key::StringKey(k)) => k,
_ => return Err(anyhow::anyhow!("Key must be a string")),
};
let value = item
.value
.ok_or(anyhow::anyhow!("Value is null for key {}", key))?;
Ok((key, Value::decode(value)?))
}
View on GitHub (pinned to bd85ce9dee)
Solutions
- Convert all map keys to strings on the host side before passing them to the BAML client (e.g. str(key) in Python)
- If non-string keys are semantically needed, encode them as strings and decode host-side after the call
- Check for JSON round-trips that convert string keys to numeric ones and normalize keys after parsing
Example fix
// before (Python)
kwargs = {1: "one"}
// after
kwargs = {str(k): v for k, v in kwargs.items()} Defensive patterns
Strategy: validation
Validate before calling
def stringify_keys(d):
if not all(isinstance(k, str) for k in d):
raise TypeError("All map keys must be strings")
return {str(k): v for k, v in d.items()}
kwargs = stringify_keys(raw_kwargs) Type guard
def has_string_keys(d: dict) -> bool:
return all(isinstance(k, str) for k in d.keys()) Try / catch
try:
result = client.CallFunction(fn, kwargs)
except Exception as e:
if "Key must be a string" in str(e):
kwargs = {str(k): v for k, v in kwargs.items()}
result = client.CallFunction(fn, kwargs)
else:
raise Prevention
- Normalize dict keys to strings at the data-source boundary (JSON, DB rows)
- Watch for languages/frameworks that allow int or bool keys in maps
- Add a pre-call schema check for kwargs key types
When it happens
Trigger: Passing a map/dict with non-string keys (int or bool keys) from the host language into a BAML function call that decodes to a Value map.
Common situations: Python/JS developers passing {1: "x"} or {True: "y"} as kwargs or map parameters; language defaults that produce integer keys from JSON-like literals.
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
- Key must be a string
- Key is missing
- Value is null for key {}
- Value is null for key {}
- Expected Collector, got {}
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/1e51532b769e0af2.
Report an issue: GitHub.