affaan-m/ECC · error · AuthenticationError

AuthenticationError(msg, provider=ProviderType.OPENAI) from…

Error message

AuthenticationError(msg, provider=ProviderType.OPENAI) from e

What it means

The OpenAI provider wraps exceptions whose message contains '401' or 'authentication' into AuthenticationError with provider=OPENAI. This means the API key was missing, malformed, revoked, or belonging to the wrong org/project.

Solutions

  1. Verify OPENAI_API_KEY is set and non-empty in the environment
  2. Regenerate the key in the OpenAI dashboard and update the secret store
  3. Strip whitespace/quotes: export OPENAI_API_KEY=$(printenv OPENAI_API_KEY | xargs)
  4. Confirm the key belongs to the correct org/project with API access

Example fix

// before
client = OpenAI(api_key="")
// after
api_key = os.environ["OPENAI_API_KEY"]
assert api_key, "OPENAI_API_KEY not set"
client = OpenAI(api_key=api_key)
Defensive patterns

Strategy: validation

Validate before calling

import os
key = os.environ.get("OPENAI_API_KEY")
assert key and key.startswith("sk-") and len(key) > 20, "OPENAI_API_KEY missing or malformed"

Try / catch

try:
    resp = provider.generate(inp)
except AuthenticationError as e:
    logger.error("OpenAI auth failed — check OPENAI_API_KEY: %s", type(e).__name__)
    raise

Prevention

When it happens

Trigger: Calling generate() with an unset OPENAI_API_KEY, a revoked/rotated key, a key from a different org without project access, or an 'Incorrect API key provided' error from the SDK.

Common situations: Missing env var in CI or deployment; key pasted with whitespace/quotes; org revoked the key; using an old sk-... key after migration to project-scoped keys.

Understand the failure class

Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/8c29d4c9232f3b6e. Report an issue: GitHub.

Appendix: source

Thrown at src/llm/providers/openai.py:117

            usage = None
            if response.usage:
                usage = {
                    "prompt_tokens": response.usage.prompt_tokens,
                    "completion_tokens": response.usage.completion_tokens,
                    "total_tokens": response.usage.total_tokens,
                }

            return LLMOutput(
                content=choice.message.content or "",
                tool_calls=tool_calls,
                model=response.model,
                usage=usage,
                stop_reason=choice.finish_reason,
            )
        except Exception as e:
            msg = str(e)
            if "401" in msg or "authentication" in msg.lower():
                raise AuthenticationError(msg, provider=ProviderType.OPENAI) from e
            if "429" in msg or "rate_limit" in msg.lower():
                raise RateLimitError(msg, provider=ProviderType.OPENAI) from e
            if "context" in msg.lower() and "length" in msg.lower():
                raise ContextLengthError(msg, provider=ProviderType.OPENAI) from e
            raise

    def list_models(self) -> list[ModelInfo]:
        return self._models.copy()

    def validate_config(self) -> bool:
        return bool(self.client.api_key)

    def get_default_model(self) -> str:
        return "gpt-4o-mini"

View on GitHub (pinned to 8321021c54)