BoundaryML/baml · error

Template string call '{}' cannot be resolved without IR cont

Error message

Template string call '{}' cannot be resolved without IR context. Use resolve_with_templates() instead.

What it means

ValueExpr::resolve cannot evaluate TemplateStringCall variants: template string calls require the intermediate representation (IR) to know the function being called. resolve deliberately fails with a pointer to the correct API, resolve_with_templates(). It is a guard against resolving IR-dependent expressions without IR context.

Source

Thrown at engine/baml-lib/baml-types/src/value_expr.rs:308

            (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 {
            Self::EnvVar(name) => ctx.get_env_var(name),
            Self::Value(value) => Ok(value.to_string()),
            Self::JinjaExpression(_) => {

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Call resolve_with_templates() with a TemplateStringRenderer implementation instead of resolve().
  2. Load/construct the IR before resolving expressions that may contain template string calls.
  3. If only env-var substitution is needed, rewrite the config value to avoid template string calls.

Example fix

// before
let key = expr.resolve(&env)?;
// after
let key = expr.resolve_with_templates(&env, &renderer)?;
Defensive patterns

Strategy: type-guard

Validate before calling

if matches!(expr, ValueExpr::TemplateStringCall { .. }) { /* must use resolve_with_templates */ }

Type guard

fn needs_ir(e: &ValueExpr) -> bool { matches!(e, ValueExpr::TemplateStringCall { .. }) }

Try / catch

let v = expr.resolve_with_templates(&env, &renderer)?;

Prevention

When it happens

Trigger: Calling resolve() on a ValueExpr::TemplateStringCall, i.e. a config/prompt value that invokes a BAML template-string function, using only an env-var provider.

Common situations: API key/header resolution where the configured value calls a template string (e.g. myFunc(...)) defined in the BAML project; running resolution before the IR is loaded.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/55f1d9f0a0cf8fb4. Report an issue: GitHub.