BoundaryML/baml · error
Expected a map
Error message
Expected a map
What it means
ValueExpr::resolve_map resolves an expression and requires the result to be ResolvedValue::Map. Any other resolved variant (or a resolution failure whose message is dropped) yields the generic error 'Expected a map'. The underlying resolve() error is not chained, so the real cause is hidden.
Source
Thrown at engine/baml-lib/baml-types/src/value_expr.rs:562
pub fn resolve_bool(&self, ctx: &impl GetEnvVar) -> Result<bool> {
match self.resolve(ctx) {
Ok(ResolvedValue::Bool(b, ..)) => Ok(b),
_ => Err(anyhow::anyhow!("Expected a boolean")),
}
}
pub fn resolve_array(&self, ctx: &impl GetEnvVar) -> Result<Vec<ResolvedValue>> {
match self.resolve(ctx) {
Ok(ResolvedValue::Array(a, ..)) => Ok(a),
_ => Err(anyhow::anyhow!("Expected an array")),
}
}
pub fn resolve_map(&self, ctx: &impl GetEnvVar) -> Result<IndexMap<String, ResolvedValue>> {
match self.resolve(ctx) {
Ok(ResolvedValue::Map(m, ..)) => Ok(m.into_iter().map(|(k, (_, v))| (k, v)).collect()),
_ => Err(anyhow::anyhow!("Expected a map")),
}
}
pub fn resolve_numeric(&self, ctx: &impl GetEnvVar) -> Result<String> {
match self.resolve(ctx) {
Ok(ResolvedValue::Numeric(n, ..)) => Ok(n),
_ => Err(anyhow::anyhow!("Expected a numeric value")),
}
}
pub fn resolve_null(&self, ctx: &impl GetEnvVar) -> Result<()> {
match self.resolve(ctx) {
Ok(ResolvedValue::Null(..)) => Ok(()),
_ => Err(anyhow::anyhow!("Expected a null value")),
}
}
pub fn resolve_serde<T: serde::de::DeserializeOwned>(&self, ctx: &impl GetEnvVar) -> Result<T> {View on GitHub (pinned to bd85ce9dee)
Solutions
- Resolve the expression with resolve() to see the actual variant and the real failure cause.
- Ensure the config value is an object/map (JSON object syntax: {"k": "v"}).
- If sourced from an env var, verify the variable is set and contains a JSON object.
- Add a fallback/default map in config when the value may be absent.
- Handle the error with context: match on resolve() yourself to surface the inner message.
Example fix
// before (env PARAMS unset)
let m = expr.resolve_map(&ctx)?; // Err: Expected a map
// after
// PARAMS='{"temperature":0.7}' or config default: {"temperature": 0.7}
let m = expr.resolve_map(&ctx)?; Defensive patterns
Strategy: validation
Validate before calling
let resolved = expr.resolve(&ctx)?;
if !matches!(resolved, ResolvedValue::Map(_)) {
bail!("value is not a map: {resolved:?}");
}
let m = expr.resolve_map(&ctx)?; Type guard
fn is_map(v: &ResolvedValue) -> bool { matches!(v, ResolvedValue::Map(..)) } Try / catch
let m = expr.resolve_map(&ctx).unwrap_or_else(|_| IndexMap::new());
Prevention
- Write object-valued config fields as JSON objects with string keys.
- Verify interpolated env vars are set and hold JSON objects.
- Check that migrations didn't turn map fields into scalars.
- Surface the inner resolve() error in your own call sites for debuggability.
When it happens
Trigger: Calling resolve_map on an expression that evaluates to a list, string, numeric, or null — e.g. a map-valued config field sourced from an env var that is unset or holds non-object JSON.
Common situations: Config sections expected to be key/value objects (params, metadata, headers) where the user supplied a scalar, or the interpolating env var is missing.
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 a string, not an array
- Expected a string, not a bool
- Expected a string, not a map
- Expected an array
- Could not unify Float with {:?}
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/566e9c4f397bc81f.
Report an issue: GitHub.