affaan-m/ECC · critical · AuthenticationError

{msg}

Error message

{msg}

What it means

OpenAIProvider.generate() raises AuthenticationError when the caught exception message contains '401' or 'authentication'. The OpenAI client is constructed with _enforce_credentials=False, so it builds happily even with an empty/missing key and fails later at request time. For the official SDK this maps to an invalid, expired, or revoked key, or a request to a model/endpoint the key's project cannot access.

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 01e15490f0)

Solutions

  1. Verify OPENAI_API_KEY is set and call provider.validate_config() (returns True when the key is non-empty) before generate().
  2. Regenerate the key in the OpenAI dashboard and rotate the stored secret.
  3. Confirm the key's project can access the requested model.
  4. If using base_url for a proxy, supply the proxy's required auth, not the OpenAI key.

Example fix

// before
provider = OpenAIProvider()
output = provider.generate(llm_input)

// after
import os
from llm.core.interface import AuthenticationError

if not os.environ.get("OPENAI_API_KEY"):
    raise SystemExit("Set OPENAI_API_KEY")
provider = OpenAIProvider()
assert provider.validate_config(), "OpenAI key missing"
try:
    output = provider.generate(llm_input)
except AuthenticationError:
    rotate_key()
    raise
Defensive patterns

Strategy: validation

Validate before calling

import os
from llm.providers.openai import OpenAIProvider

def openai_ready() -> bool:
    return bool(os.environ.get("OPENAI_API_KEY")) and OpenAIProvider().validate_config()

Type guard

from llm.core.interface import AuthenticationError

def is_auth_error(exc: BaseException) -> bool:
    return isinstance(exc, AuthenticationError)

Try / catch

from llm.core.interface import AuthenticationError

try:
    output = provider.generate(llm_input)
except AuthenticationError as e:
    logger.error("OpenAI auth failed — rotate key: %s", e)
    raise

Prevention

When it happens

Trigger: OPENAI_API_KEY unset or empty (client still constructs due to _enforce_credentials=False); key revoked or rotated; key lacks permission for the requested model; base_url points at a proxy that requires its own auth.

Common situations: Missing .env / env var; CI secret not injected; key rotated but old value cached; using an org key for a model in a different project; Azure/proxy base_url with a credential meant for another backend.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/b73675af86d10ca2. Report an issue: GitHub.