BerriAI/litellm · error · ValueError

OpenRouter API key is required. Set OPENROUTER_API_KEY envir

Error message

OpenRouter API key is required. Set OPENROUTER_API_KEY environment variable or pass api_key parameter.

What it means

OpenRouter's Responses API transformation builds auth headers before any request: it checks litellm_params.api_key, then the global litellm.api_key, then the OPENROUTER_API_KEY and OR_API_KEY environment variables. If all are empty it raises this ValueError; nothing is sent over the network.

Source

Thrown at litellm/llms/openrouter/responses/transformation.py:51

    def custom_llm_provider(self) -> LlmProviders:
        return LlmProviders.OPENROUTER

    def validate_environment(
        self,
        headers: dict,
        model: str,
        litellm_params: GenericLiteLLMParams | None,
    ) -> dict:
        litellm_params = litellm_params or GenericLiteLLMParams()
        api_key: Final = (
            litellm_params.api_key
            or litellm.api_key
            or get_secret_str("OPENROUTER_API_KEY")
            or get_secret_str("OR_API_KEY")
        )

        if not api_key:
            raise ValueError(
                "OpenRouter API key is required. Set OPENROUTER_API_KEY environment variable or pass api_key parameter."
            )

        headers.update(
            {
                "Authorization": f"Bearer {api_key}",
            }
        )
        return headers

    def get_complete_url(
        self,
        api_base: str | None,
        litellm_params: dict,
    ) -> str:
        api_base = (
            api_base or litellm.api_base or get_secret_str("OPENROUTER_API_BASE") or "https://openrouter.ai/api/v1"
        )

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. export OPENROUTER_API_KEY=sk-or-... in the environment that actually runs litellm
  2. Pass the key per call: litellm.responses(model='openrouter/...', api_key='sk-or-...')
  3. Alternatively set the accepted alias OR_API_KEY
  4. For litellm proxy, configure api_key on the openrouter deployment in config.yaml instead of relying on ambient env

Example fix

// before
resp = litellm.responses(model="openrouter/openai/gpt-4o", input="hello")

// after
import os
resp = litellm.responses(model="openrouter/openai/gpt-4o", input="hello", api_key=os.environ["OPENROUTER_API_KEY"])
Defensive patterns

Strategy: validation

Validate before calling

import os, litellm

def openrouter_key_present() -> bool:
    return bool(
        litellm.api_key
        or os.getenv("OPENROUTER_API_KEY")
        or os.getenv("OR_API_KEY")
    )

assert openrouter_key_present(), "OPENROUTER_API_KEY (or OR_API_KEY) must be set"  # run at startup

Try / catch

try/except ValueError around litellm.responses calls can convert the failure into a clear configuration error for ops (the exception is deterministic - no retry makes sense).

Prevention

When it happens

Trigger: Calling litellm.responses(model='openrouter/...') without an api_key argument while neither OPENROUTER_API_KEY nor OR_API_KEY is set in the process environment (including the OR_API_KEY alias).

Common situations: Key exported in an interactive shell but missing in the container/service/cron environment; .env file not loaded before litellm runs; typo in the variable name; proxy deployments where the key was configured on a different virtual key/deployment.

Related errors


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