BerriAI/litellm · error · ValueError

API key is required

Error message

API key is required

What it means

generate_iam_token exchanges your WatsonX API key for an IBM IAM access token by POSTing to https://iam.cloud.ibm.com/identity/token. The key is taken from the api_key argument or the env chain WX_API_KEY / WATSONX_API_KEY / WATSONX_APIKEY / WATSONX_ZENAPIKEY; if all are empty, this bare ValueError('API key is required') is raised before the IAM call. It fires when you authenticate with api_key (as opposed to passing a ready-made token).

Source

Thrown at litellm/llms/watsonx/common_utils.py:46

def get_watsonx_iam_url():
    return get_secret_str("WATSONX_IAM_URL") or "https://iam.cloud.ibm.com/identity/token"


def generate_iam_token(api_key=None, **params) -> str:
    result: str | None = iam_token_cache.get_cache(api_key)

    if result is None:
        headers: Final = {}
        headers["Content-Type"] = "application/x-www-form-urlencoded"
        if api_key is None:
            api_key = (
                get_secret_str("WX_API_KEY")
                or get_secret_str("WATSONX_API_KEY")
                or get_secret_str("WATSONX_APIKEY")
                or get_secret_str("WATSONX_ZENAPIKEY")
            )
        if api_key is None:
            raise ValueError("API key is required")
        headers["Accept"] = "application/json"
        data: Final = {
            "grant_type": "urn:ibm:params:oauth:grant-type:apikey",
            "apikey": api_key,
        }
        iam_token_url: Final = get_watsonx_iam_url()
        verbose_logger.debug(
            "calling ibm `/identity/token` to retrieve IAM token.\nURL=%s\nheaders=%s\ndata=%s",
            iam_token_url,
            headers,
            data,
        )
        response: Final = litellm.module_level_client.post(url=iam_token_url, data=data, headers=headers)
        response.raise_for_status()
        json_data: Final = response.json()

        result = json_data["access_token"]
        iam_token_cache.set_cache(

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. export WATSONX_APIKEY=<key> (or WX_API_KEY / WATSONX_API_KEY / WATSONX_ZENAPIKEY).
  2. Or pass api_key directly to the call / proxy model config.
  3. If you already have an IAM token, pass token=... (or watsonx_token) instead - that path skips generate_iam_token.
  4. Add a preflight check that at least one of the four env vars is non-empty.

Example fix

# before
resp = litellm.completion(model="watsonx/mistralai/mistral-large", messages=[{"role": "user", "content": "hi"}])
# -> ValueError: API key is required (from IAM token exchange)

# after
import os
os.environ["WATSONX_APIKEY"] = "<your-ibm-apikey>"
os.environ["WATSONX_PROJECT_ID"] = "<your-project-id>"
resp = litellm.completion(model="watsonx/mistralai/mistral-large", messages=[{"role": "user", "content": "hi"}])
Defensive patterns

Strategy: validation

Validate before calling

import os

WX_KEY = (
    os.getenv("WX_API_KEY")
    or os.getenv("WATSONX_API_KEY")
    or os.getenv("WATSONX_APIKEY")
    or os.getenv("WATSONX_ZENAPIKEY")
)
if not WX_KEY and not os.getenv("WATSONX_TOKEN"):
    raise RuntimeError("WatsonX needs an API key (WX_API_KEY, WATSONX_APIKEY, ...) or a token")
resp = litellm.completion(model="watsonx/...", messages=msgs)

Type guard

const hasWatsonxAuth = (env: Record<string, string | undefined>): boolean =>
  Boolean(
    env.WX_API_KEY ?? env.WATSONX_API_KEY ?? env.WATSONX_APIKEY ??
    env.WATSONX_ZENAPIKEY ?? env.WATSONX_TOKEN
  );

Try / catch

try:
    resp = litellm.completion(model="watsonx/...", messages=msgs)
except ValueError as e:
    if str(e) == "API key is required":
        raise RuntimeError("Set WATSONX_APIKEY (or pass token=) for WatsonX IAM auth") from e
    raise

Prevention

When it happens

Trigger: litellm.completion(model="watsonx/...", messages=[...]) without api_key/token and with none of the four env vars set; using WATSONX_API_KEY_TYPO-style names; Zen-style deployments (WATSONX_ZENAPIKEY) missing in local dev.

Common situations: Local runs where keys live only in the deployed environment; notebooks that never call load_dotenv; migrations from IBM Watson Studio env var conventions to litellm; service containers with scrubbed env.

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/7d0d227f606f11f2. Report an issue: GitHub.