langchain-ai/deepagents · error · RuntimeError
{field} references unset env var {name}. Set {name} in the e
Error message
{field} references unset env var {name}. Set {name} in the environment or provide a default. What it means
`_interpolate_env` expands `${VAR}` references in MCP config string fields. A `${VAR}` reference (no `:-default`) whose variable is unset in `os.environ` is the only hard error: it raises `RuntimeError` naming the field and variable, so a typo or missing secret cannot silently inject an empty value into a URL, command, or header.
Source
Thrown at libs/code/deepagents_code/mcp_config.py:71
name = match.group(1)
default = match.group(2)
resolved = os.environ.get(name)
# A non-empty value always wins, for both `${VAR}` and `${VAR:-default}`.
if resolved:
return resolved
# `resolved` is now "" (set but empty) or None (unset).
if default is not None:
# `${VAR:-default}`: `:-` falls back for empty *and* unset (POSIX).
return default
if resolved is not None:
# `${VAR}` set to "": no default, so emit the empty value.
return resolved
# `${VAR}` unset with no default: the only hard error.
msg = (
f"{field} references unset env var {name}. "
f"Set {name} in the environment or provide a default."
)
raise RuntimeError(msg)
# Reject any `${` that isn't the start of a well-formed reference. The
# check is against the raw `value` (not the substituted result) so a
# resolved value that happens to contain `${` never trips it.
ref_spans = [match.span() for match in _ENV_REF_RE.finditer(value)]
for brace in _ENV_BRACE_RE.finditer(value):
if not any(start <= brace.start() < end for start, end in ref_spans):
msg = (
f"{field} contains a malformed '${{...}}' reference. "
"Use '${VAR}' or '${VAR:-default}'."
)
raise RuntimeError(msg)
return _ENV_REF_RE.sub(replace, value)
def _resolve_string(value: object, *, field: str) -> str:
"""Validate and interpolate one string field.View on GitHub (pinned to a1af029e6e)
Solutions
- Set the named env var in the environment before launching (`export NAME=value`).
- Change the config to `${NAME:-default}` so an unset variable falls back to a default.
- Remove or rename the reference if the variable is obsolete — note only braced `${VAR}` expands; a bare `$VAR` passes through.
Example fix
// before
{"url": "${ACME_API_URL}"} # ACME_API_URL unset -> RuntimeError
// after
{"url": "${ACME_API_URL:-https://api.acme.dev}"} Defensive patterns
Strategy: validation
Validate before calling
import os, re
REF = re.compile(r"\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-([^{}]*))?\}")
def missing_vars(value: str) -> list[str]:
refs = REF.findall(value)
return [name for name, default in refs if not default and not os.environ.get(name)]
# e.g. missing_vars(cfg["url"]) -> ["MY_API_URL"] before calling the API Type guard
def env_available(name: str) -> bool:
return bool(os.environ.get(name)) Try / catch
try:
resolved = resolve_mcp_server_env(server_name, server_config)
except RuntimeError as exc:
if "references unset env var" in str(exc):
var = str(exc).split("env var ")[1].split(".")[0]
raise SystemExit(f"Set {var} before launching (export {var}=...)") from exc
raise Prevention
- Prefer `${VAR:-default}` for anything optional
- Check `env | grep VARNAME` before running the command if the config interpolates it
- Remember containers/CI and GUI launchers do not inherit your shell env — set vars explicitly
- Only `${VAR}` expands; a bare `$VAR` passes through unexpanded, so don't rely on it
When it happens
Trigger: Calling `resolve_mcp_server_env(server_name, server_config)` (directly or via login/connect) where a supported field value contains `${NAME}` and `NAME` is not present in `os.environ` and no `${NAME:-default}` form is used.
Common situations: A CI/container where the API-key or base-URL env var was never exported; shell config changed so a variable is no longer set; shared config copied between machines that define different variables; macOS launchers that don't inherit shell env.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- {str(exc)}
- {field} contains a malformed '${{...}}' reference. Use '${VA
- {field} must be a string, got {type(value).__name__}
- {prefix}.args must be a list, got {type(args).__name__}
- Server '{server_name}' 'headers' must be a dictionary
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/e8bfc1183075b986.
Report an issue: GitHub.