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

  1. Set the named env var in the environment before launching (`export NAME=value`).
  2. Change the config to `${NAME:-default}` so an unset variable falls back to a default.
  3. 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

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


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/e8bfc1183075b986. Report an issue: GitHub.