langchain-ai/deepagents · error · ValueError

API key cannot be empty

Error message

API key cannot be empty

What it means

`set_stored_key` strips whitespace from the supplied API key and raises `ValueError` if the result is empty. This prevents storing a blank credential that would silently fail at request time, and catches the common whitespace-only paste mistake.

Source

Thrown at libs/code/deepagents_code/auth_store.py:475

    Returns:
        A `WriteOutcome` whose `warnings` tuple lists chmod failures the
        caller should surface to the user. Empty on a clean save.

    Raises:
        ValueError: If `provider` or the stripped `key` is empty, or a non-empty
            `project` is paired with a provider other than the `langsmith`
            service.
        RuntimeError: If the credential file is corrupt and cannot be read, or
            the new file cannot be written (e.g. no disk space or an
            unwritable state directory).
    """  # noqa: DOC502 - `RuntimeError` re-raised from `_read_raw`/`_write_raw_or_raise`
    if not provider:
        msg = "Provider name cannot be empty"
        raise ValueError(msg)
    cleaned = key.strip()
    if not cleaned:
        msg = "API key cannot be empty"
        raise ValueError(msg)
    data = _read_raw() or {}
    creds = data.get("credentials")
    if not isinstance(creds, dict):
        creds = {}
    entry: dict[str, str] = {
        "type": "api_key",
        "key": cleaned,
        "added_at": datetime.now(tz=UTC).isoformat(timespec="seconds"),
    }
    cleaned_base_url = base_url.strip() if base_url else ""
    if cleaned_base_url:
        entry["base_url"] = cleaned_base_url
    cleaned_project = project.strip() if project else ""
    if cleaned_project:
        # A project name is meaningful only for the LangSmith tracing service;
        # enforce the invariant at the write boundary so a stray project can
        # never be persisted onto an unrelated provider, regardless of caller.
        # Lazy import avoids a circular dependency (model_config imports this

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Supply the actual API key string, e.g. set_stored_key("anthropic", "sk-...").
  2. Check the source env var / config value is populated before calling (fail fast with a clear message).
  3. Re-run /auth and paste the full key, including any prefixes like `sk-` or `lsv2_`.

Example fix

// before
key = os.environ.get("ANTHROPIC_API_KEY", "")
set_stored_key("anthropic", key)  # ValueError if unset
// after
key = os.environ.get("ANTHROPIC_API_KEY")
if not key or not key.strip():
    raise SystemExit("ANTHROPIC_API_KEY is not set")
set_stored_key("anthropic", key)
Defensive patterns

Strategy: validation

Validate before calling

def require_key(provider: str, key: str | None) -> str:
    cleaned = (key or "").strip()
    if not cleaned:
        raise UsageError(f"API key for {provider} is required")
    return cleaned
# call site
set_stored_key(provider, require_key(provider, os.environ.get("ANTHROPIC_API_KEY")))

Type guard

def _is_nonempty_str(value: object) -> TypeGuard[str]:
    return isinstance(value, str) and bool(value.strip())

Try / catch

try:
    set_stored_key(provider, key)
except ValueError as exc:
    if "API key cannot be empty" in str(exc):
        print(f"no API key supplied for {provider}; set the env var or re-run /auth")
    else:
        raise

Prevention

When it happens

Trigger: Calling set_stored_key(provider, "") or set_stored_key(provider, " "), or via `_run_set`/`on_input_submitted` when the user submits an empty or whitespace-only key.

Common situations: Environment variable holding the key is unset so the script passes an empty string; copy-paste missed the actual key and grabbed only whitespace; a config file line like `KEY=` resolved to empty.

Related errors


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