BoundaryML/baml · error
Jinja expressions cannot be resolved without a template cont
Error message
Jinja expressions cannot be resolved without a template context
What it means
ValueExpr::resolve handles only statically-known variants: EnvVar and Value. JinjaExpression needs a rendered template context to evaluate, so resolve explicitly rejects it with this error instead of silently producing a wrong string. The variant is not an error per se — the wrong resolution API was used.
Source
Thrown at engine/baml-lib/baml-types/src/value_expr.rs:305
pub fn maybe_eq(&self, other: &StringOr) -> bool {
match (self, other) {
(Self::Value(s), Self::Value(o)) => s == o,
(Self::Value(_), _) | (_, Self::Value(_)) => true,
(Self::EnvVar(_), Self::JinjaExpression(_))
| (Self::JinjaExpression(_), Self::EnvVar(_)) => true,
(Self::JinjaExpression(_), Self::JinjaExpression(_)) => true,
(Self::EnvVar(s), Self::EnvVar(o)) => s == o,
// Template string calls could evaluate to anything, so conservatively return true
(Self::TemplateStringCall { .. }, _) | (_, Self::TemplateStringCall { .. }) => true,
}
}
pub fn resolve(&self, ctx: &impl GetEnvVar) -> Result<String> {
match self {
Self::EnvVar(name) => ctx.get_env_var(name),
Self::Value(value) => Ok(value.to_string()),
Self::JinjaExpression(_) => {
anyhow::bail!("Jinja expressions cannot be resolved without a template context")
}
Self::TemplateStringCall { name, .. } => {
anyhow::bail!(
"Template string call '{}' cannot be resolved without IR context. \
Use resolve_with_templates() instead.",
name
)
}
}
}
/// Resolve this StringOr, with support for template_string calls.
pub fn resolve_with_templates(
&self,
ctx: &impl GetEnvVar,
template_renderer: &impl TemplateStringRenderer,
) -> Result<String> {
match self {View on GitHub (pinned to bd85ce9dee)
Solutions
- Use resolve_with_templates() (or the full IR-aware resolver) which supplies a template context.
- Ensure a template renderer is available where the ValueExpr is resolved.
- If the value should be static, replace the Jinja expression in the configuration with a literal or env-var reference.
Example fix
// before let v = expr.resolve(&env)?; // after let v = expr.resolve_with_templates(&env, &template_renderer)?;
Defensive patterns
Strategy: type-guard
Validate before calling
if matches!(expr, ValueExpr::JinjaExpression(_) | ValueExpr::TemplateStringCall { .. }) { return Err(anyhow!("needs template-aware resolver")); } Type guard
fn is_statically_resolvable(e: &ValueExpr) -> bool { matches!(e, ValueExpr::EnvVar(_) | ValueExpr::Value(_)) } Try / catch
let v = expr.resolve_with_templates(&env, &renderer).map_err(|e| anyhow!("resolution failed: {}", e))?; Prevention
- Use resolve_with_templates when configs may contain Jinja
- Validate ValueExpr variants before choosing a resolver
- Keep a template renderer available wherever config resolution happens
When it happens
Trigger: Calling resolve() on a ValueExpr that contains Self::JinjaExpression, e.g. resolving API key expressions or config values that embed {{ ... }} Jinja expressions without a template context.
Common situations: Resolving client/API-key configuration strings that users wrote with Jinja expressions (e.g. dynamic headers) via the simple env-var-only resolver.
Related errors
- Encountered impossible jinja expression during parsing
- Failed to parse template '{}': {}
- Failed to get template '{}': {}
- BamlImage has no callable attribute '{args:#?}'
- Expected a statically defined string, not expression
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/d24022216b3f6f2e.
Report an issue: GitHub.