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
- Check the variable name in the error message against your .baml file for typos and fix the identifier
- Ensure the variable is declared/assigned before the expression that references it
- Verify the variable is in scope (not referenced outside the function/let block that defines it)
- 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
- Run the BAML type checker before interpretation to catch undeclared identifiers
- Use an editor plugin/LSP for .baml files to flag unknown names
- Grep for renamed variables after refactors to find stale references
- Keep function parameters explicit and avoid relying on ambient bindings
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
- Variable ' ' not found for $watch.notify()
- arity mismatch: expected
- array access on non-list at
- array assignment index out of bounds
- array assignment on non-list value at
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)