BoundaryML/baml · error
Expected a string, not a map
Error message
Expected a string, not a map
What it means
as_static_str expects a string-typed UnresolvedValue; a Map (BAML object literal with key/value pairs) cannot be returned as &str, so it bails. The library throws this to keep static string reads type-safe rather than implicitly serializing objects.
Source
Thrown at engine/baml-lib/baml-types/src/value_expr.rs:530
}
impl<Meta> UnresolvedValue<Meta> {
pub fn as_static_str(&self) -> Result<&str> {
match self {
Self::String(StringOr::Value(v), ..) => Ok(v.as_str()),
Self::String(StringOr::EnvVar(..), ..) => {
anyhow::bail!("Expected a statically defined string, not env variable")
}
Self::String(StringOr::JinjaExpression(..), ..) => {
anyhow::bail!("Expected a statically defined string, not expression")
}
Self::String(StringOr::TemplateStringCall { .. }, ..) => {
anyhow::bail!("Expected a statically defined string, not a template_string call")
}
Self::Numeric(num, ..) => Ok(num.as_str()),
Self::Array(..) => anyhow::bail!("Expected a string, not an array"),
Self::Bool(..) => anyhow::bail!("Expected a string, not a bool"),
Self::Map(..) => anyhow::bail!("Expected a string, not a map"),
Self::Null(..) => anyhow::bail!("Expected a string, not null"),
Self::ClassConstructor(..) => {
anyhow::bail!("Expected a string, not a class constructor")
}
}
}
pub fn resolve_string(&self, ctx: &impl GetEnvVar) -> Result<String> {
match self.resolve(ctx) {
Ok(ResolvedValue::String(s, ..)) => Ok(s),
_ => Err(anyhow::anyhow!("Expected a string")),
}
}
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")),View on GitHub (pinned to bd85ce9dee)
Solutions
- Replace the map literal with the specific string field/value required
- Read the field with resolve_map(ctx) and extract the needed entry in code
- Align the .baml schema so the field's declared type matches the authored value
Example fix
// before (baml)
options {
model { name: "gpt-4o" }
}
// after (baml)
options {
model "gpt-4o"
} Defensive patterns
Strategy: validation
Validate before calling
// Rust
if matches!(v, UnresolvedValue::Map(..)) {
anyhow::bail!("expected a string field, got an object/map");
}
let s = v.as_static_str()?; Type guard
fn is_string_value<Meta>(v: &UnresolvedValue<Meta>) -> bool {
matches!(v, UnresolvedValue::String(_, _))
} Prevention
- Keep scalar fields scalar; nest objects only where the schema allows
- Use resolve_map for structured fields
- Lint baml_src for object literals in string-typed positions
When it happens
Trigger: Calling as_static_str() on UnresolvedValue::Map(..) — a BAML field authored as an object/map literal ({ key: "value" }) but read through the string accessor.
Common situations: Nesting config by mistake (e.g. putting an options object where a scalar string belongs), or JSON-style config copied into a field that must be a plain string.
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 an array
- Expected a map
- Could not unify Float with {:?}
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/1c6462a5ef7a9189.
Report an issue: GitHub.