BoundaryML/baml · error
Expected a statically defined string, not expression
Error message
Expected a statically defined string, not expression
What it means
as_static_str only returns values that are literal strings (or numerics) written directly in BAML source. A Jinja expression (e.g. "{{ something }}") needs evaluation at runtime, so the static accessor rejects it. The library throws this because a static string is required where the value is used (e.g. names, enum tags, provider fields) and an expression cannot be known at parse time.
Source
Thrown at engine/baml-lib/baml-types/src/value_expr.rs:522
impl Default for EvaluationContext<'_> {
fn default() -> Self {
Self {
env_vars: None,
fill_missing_env_vars: true,
}
}
}
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),View on GitHub (pinned to bd85ce9dee)
Solutions
- Replace the Jinja expression with a static quoted string literal in the .baml file
- Move the dynamic interpolation to a place where it is allowed (e.g. prompt bodies, not static identifiers)
- In consuming Rust code, use resolve_string(&ctx) (with a context that can render the expression) instead of as_static_str()
Example fix
// before (baml)
enum Sentiment {
"{{ Positive }}"
}
// after (baml)
enum Sentiment {
Positive
} Defensive patterns
Strategy: validation
Validate before calling
// Rust
if matches!(v, UnresolvedValue::String(StringOr::JinjaExpression(_), _)) {
anyhow::bail!("Jinja expressions are not allowed in this static field");
}
let s = v.as_static_str()?; Type guard
fn is_static_string<Meta>(v: &UnresolvedValue<Meta>) -> bool {
matches!(v, UnresolvedValue::String(StringOr::Value(_), _))
} Prevention
- Use Jinja only inside prompt bodies, never in static identifiers/options
- Validate baml_src early with a linter that flags expressions in scalar fields
- Resolve expressions at runtime with resolve_string when dynamism is required
When it happens
Trigger: Calling as_static_str() on UnresolvedValue::String(StringOr::JinjaExpression(..)) — a BAML field whose value is a Jinja template expression like {{ ctx.field }} or {{ _.name }} instead of a quoted literal.
Common situations: Developers interpolate dynamic values into BAML fields that must be static (client names, enum variant values, metadata strings), or copy template-style config between fields, then a static validation/registration pass fails.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Failed to get template '{}': {}
- Expected a statically defined string, not a template_string
- Failed to parse template '{}': {}
- Failed to render template '{}': {}
- Expected a statically defined string, not env variable
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/b0adba2e1ffe4061.
Report an issue: GitHub.