BoundaryML/baml · error

Environment variable

Error message

Environment variable '{}' not found

What it means

The BAML interpreter evaluates an Expr::Var identifier by looking it up in the current environment scope map. When the key is absent from every scope it throws "Environment variable '{}' not found", meaning an identifier was referenced that was never declared or bound in the visible scope. This is the interpreter's equivalent of an unresolved-name/undefined-variable error.

Solutions

  1. Check the variable name in the error message against your .baml file for typos and fix the identifier
  2. Ensure the variable is declared/assigned before the expression that references it
  3. Verify the variable is in scope (not referenced outside the function/let block that defines it)
  4. If it is a builtin or externally provided value, confirm the interpreter version supports binding it; upgrade baml

Example fix

// before
let result = undefined_var + 1
// after
let undefined_var = 5
let result = undefined_var + 1
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check identifiers used in a BAML expression against declared bindings
function validateIdentifiers(exprVars: string[], declared: Set<string>): string[] {
  return exprVars.filter(v => !declared.has(v)); // empty means safe to evaluate
}

Type guard

function isBound(name: string, scopes: Record<string, unknown>[]): boolean {
  return scopes.some(s => Object.prototype.hasOwnProperty.call(s, name));
}

Try / catch

try {
  const result = evalBaml(expr, env);
} catch (e) {
  if (String(e).includes("Environment variable")) {
    const name = /'([^']+)'/.exec(String(e))?.[1];
    throw new Error(`Undeclared BAML variable '${name}' — declare it before use`);
  }
  throw e;
}

Prevention

When it happens

Trigger: Evaluating a BAML expression that references a variable name not present in any active scope (e.g. a typo, use-before-declaration, or a variable only available at compile/check time but missing in the interpreter's environment map during evaluate_expr_with_context).

Common situations: Renaming a variable in a .baml file but missing a usage; referencing a function parameter from outside its scope; runtime interpretation (tests, preview) of code that type-checks only partially; interpreter not yet supporting some bindings the compiled path provides.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at engine/baml-compiler/src/thir/interpret.rs:1799

                        )?;

                        let key = match key_val {
                            BamlValueWithMeta::String(value, _) => value,
                            _ => bail!("env.get argument must be a string"),
                        };

                        let env_map = lookup(scopes, "__env_vars__")
                            .ok_or_else(|| anyhow!("environment context missing"))?;

                        let map = match env_map {
                            BamlValueWithMeta::Map(ref entries, _) => entries,
                            _ => bail!("environment context corrupted"),
                        };

                        if let Some(value) = map.get(&key) {
                            return Ok(EvalValue::Value(value.clone()));
                        } else {
                            bail!("Environment variable '{}' not found", key);
                        }
                    }
                }

                let callee = evaluate_expr(
                    func,
                    scopes,
                    thir,
                    run_llm_function,
                    watch_handler,
                    function_name,
                )
                .await?;
                let (arity, body, meta) = match callee {
                    EvalValue::Function(a, b, m) => (a, b, m),
                    _ => bail!("attempted to call non-function"),
                };

View on GitHub (pinned to bd85ce9dee)