BerriAI/litellm · error · Exception

Authentication failed. Check your Arize Phoenix API key and…

Error message

Authentication failed. Check your Arize Phoenix API key and permissions.

What it means

ArizePhoenixClient.get_prompt_version converts HTTP 401 into this Exception: the Bearer token was rejected — missing, malformed, expired, or simply not a valid Phoenix API key. Note the client always sends Authorization: Bearer <api_key>, so any non-empty but wrong key lands here rather than failing earlier.

Solutions

  1. Regenerate the API key in Phoenix (Settings -> API Keys) and update PHOENIX_API_KEY / the api_key param
  2. Strip whitespace: `export PHOENIX_API_KEY=$(printf '%s' "$PHOENIX_API_KEY")` or check for trailing newline in CI secrets
  3. Confirm you are using a Phoenix API key, not a collector/OTLP header or a different product's key
Defensive patterns

Strategy: validation

Validate before calling

import httpx, os

resp = httpx.get(
    f"{api_base}/prompt_versions/{prompt_version_id}",
    headers={"Authorization": f"Bearer {os.environ['PHOENIX_API_KEY']}"},
    timeout=5,
)
if resp.status_code == 401:
    raise SystemExit("PHOENIX_API_KEY rejected (401) — regenerate the key in Phoenix settings")

Try / catch

try:
    manager.compile(prompt_id=prompt_id, prompt_variables=vars)
except Exception as e:
    if "Authentication failed" in str(e):
        raise SystemExit("Invalid PHOENIX_API_KEY — check for stale/rotated key or stray whitespace") from e
    raise

Prevention

When it happens

Trigger: Calling get_prompt_version (directly or via the litellm prompt manager loading a prompt) with an incorrect, revoked, or expired PHOENIX_API_KEY. 404 maps to None and 403 to the permissions error; 401 reaches this branch.

Common situations: Using an OTLP export header value or Phoenix UI session token instead of an API key; key deleted/rotated in Phoenix while the old one is still deployed; whitespace/newline accidentally included in the env var value.

Understand the failure class

Related errors


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

Appendix: source

Thrown at litellm/integrations/arize/arize_phoenix_client.py:88

            # Use the underlying httpx client directly to avoid query param extraction
            response = self.http_handler.get(url, headers=self.headers)
            response.raise_for_status()

            data: Final = response.json()
            return data.get("data")

        except Exception as e:
            # Check if it's an HTTP error
            response = getattr(e, "response", None)
            if response is not None and hasattr(response, "status_code"):
                if response.status_code == 404:
                    return None
                elif response.status_code == 403:
                    raise Exception(
                        f"Access denied to prompt version '{prompt_version_id}'. Check your Arize Phoenix permissions."
                    )
                elif response.status_code == 401:
                    raise Exception("Authentication failed. Check your Arize Phoenix API key and permissions.")
                else:
                    raise Exception(f"Failed to fetch prompt version '{prompt_version_id}': {e}")
            else:
                raise Exception(f"Error fetching prompt version '{prompt_version_id}': {e}")

    def test_connection(self) -> bool:
        """
        Test the connection to the Arize Phoenix API.

        Returns:
            True if connection is successful, False otherwise
        """
        try:
            # Try to access the prompt_versions endpoint to test connection
            url: Final = f"{self.api_base}/prompt_versions"
            response: Final = self.http_handler.client.get(url, headers=self.headers)
            response.raise_for_status()
            return True

View on GitHub (pinned to 77b7c6c40c)