{"record":{"id":"5339234a7f327b79","repo":"affaan-m/ECC","slug":"msg-533923","errorCode":null,"errorMessage":"msg","messagePattern":"msg","errorType":"exception","errorClass":"AuthenticationError","httpStatus":null,"severity":"critical","filePath":"src/llm/providers/astraflow.py","lineNumber":116,"sourceCode":"            usage = None\n            if response.usage:\n                usage = {\n                    \"prompt_tokens\": response.usage.prompt_tokens,\n                    \"completion_tokens\": response.usage.completion_tokens,\n                    \"total_tokens\": response.usage.total_tokens,\n                }\n\n            return LLMOutput(\n                content=choice.message.content or \"\",\n                tool_calls=tool_calls,\n                model=response.model,\n                usage=usage,\n                stop_reason=choice.finish_reason,\n            )\n        except Exception as e:\n            msg = str(e)\n            if \"401\" in msg or \"authentication\" in msg.lower():\n                raise AuthenticationError(msg, provider=self.provider_type) from e\n            if \"429\" in msg or \"rate_limit\" in msg.lower():\n                raise RateLimitError(msg, provider=self.provider_type) from e\n            if \"context\" in msg.lower() and \"length\" in msg.lower():\n                raise ContextLengthError(msg, provider=self.provider_type) from e\n            raise\n\n    def list_models(self) -> list[ModelInfo]:\n        return self._models.copy()\n\n    def validate_config(self) -> bool:\n        return bool(self.api_key)\n\n    def get_default_model(self) -> str:\n        return self.default_model\n\n\nclass AstraflowProvider(_AstraflowBaseProvider):\n    \"\"\"UModelVerse global endpoint using OpenAI-compatible chat completions.\"\"\"","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/affaan-m/ECC/blob/d8409a4b0813771235555e32e3d8046a73988bfa/src/llm/providers/astraflow.py#L98-L134","documentation":"In AstraFlowProvider.generate()'s except block (src/llm/providers/astraflow.py:118), any exception whose string form contains '401' or 'authentication' (case-insensitive) is re-raised as AuthenticationError(msg, provider=...) with the original as __cause__. The reported message 'msg' in catalogs is the captured str(e) of the underlying SDK exception — commonly an openai.AuthenticationError with 'Error code: 401'.","triggerScenarios":"Invalid, missing, or revoked API key; key for the wrong project/environment; Authorization header stripped by a proxy; expired token; key typo'd in the provider config (validate_config() only checks truthiness, so a wrong-but-present key passes config validation and fails here at request time).","commonSituations":"API key read from an env var that is unset in the deployed environment (falls back to an empty/placeholder value); rotating keys and forgetting one consumer; using a key from a different region/gateway; local .env not loaded.","solutions":["Verify the API key is the correct, active key for this provider and set it in the environment the process actually sees.","Print/dump the resolved config (never the key itself) and confirm the key variable name matches what the provider reads.","Test the key directly with a minimal curl/SDK call to the provider endpoint to isolate harness vs. credential issues.","Rotate the key if it may have leaked or been revoked."],"exampleFix":"# before\nprovider = AstraFlowProvider(api_key=os.environ.get(\"ASTRAFLOW_API_KEY\", \"\"))\nout = provider.generate(inp)  # AuthenticationError: Error code: 401 ...\n\n# after: fail fast on missing credentials\napi_key = os.environ[\"ASTRAFLOW_API_KEY\"]  # KeyError at startup, not 401 at request time\nprovider = AstraFlowProvider(api_key=api_key)\nassert provider.validate_config()","handlingStrategy":"try-catch","validationCode":"import os\n\ndef astraflow_config_ok() -> bool:\n    key = os.environ.get(\"ASTRAFLOW_API_KEY\", \"\")\n    return bool(key) and not key.startswith(\"sk-placeholder\")  # presence check only; real check is a live call","typeGuard":null,"tryCatchPattern":"from src.llm.core.interface import AuthenticationError\n\ntry:\n    out = provider.generate(inp)\nexcept AuthenticationError:\n    # credentials are wrong/revoked — never retry, alert instead\n    alerts.critical(\"AstraFlow auth failed; rotate ASTRAFLOW_API_KEY\")\n    raise","preventionTips":["Load the API key with a required-env lookup at startup so misconfig fails before traffic.","validate_config() only checks presence — smoke-test credentials with one live call at boot.","Rotate keys on schedule and keep per-environment keys separate."],"tags":["llm","authentication","api-key","http-401","astraflow","python"],"backgroundTag":"llm-api-authentication-failed","analyzedSha":"d8409a4b0813771235555e32e3d8046a73988bfa","analyzedAt":"2026-08-26T12:15:34.022Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}