{"record":{"id":"d37e89e4f5f846e0","repo":"666ghj/MiroFish","slug":"llm-api-key-d37e89","errorCode":null,"errorMessage":"LLM_API_KEY 未配置","messagePattern":"LLM_API_KEY 未配置","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"backend/app/utils/llm_client.py","lineNumber":105,"sourceCode":"            return True\n    return False\n\n\nclass LLMClient:\n    \"\"\"LLM客户端\"\"\"\n    \n    def __init__(\n        self,\n        api_key: Optional[str] = None,\n        base_url: Optional[str] = None,\n        model: Optional[str] = None\n    ):\n        self.api_key = api_key or Config.LLM_API_KEY\n        self.base_url = base_url or Config.LLM_BASE_URL\n        self.model = model or Config.LLM_MODEL_NAME\n        \n        if not self.api_key:\n            raise ValueError(\"LLM_API_KEY 未配置\")\n        \n        self.client = OpenAI(\n            api_key=self.api_key,\n            base_url=self.base_url\n        )\n\n    def _create_completion(\n        self,\n        *,\n        messages: List[Dict[str, str]],\n        temperature: Optional[float],\n        max_tokens: Optional[int],\n        response_format: Optional[Dict[str, Any]],\n    ) -> Any:\n        \"\"\"Send one raw Chat Completions request through the compatibility layer.\"\"\"\n\n        return create_chat_completion(\n            self.client,","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/666ghj/MiroFish/blob/b5b53acc57189a4a42e44a23e149dc655c98fe82/backend/app/utils/llm_client.py#L87-L123","documentation":"ValueError raised in LLMClient.__init__ when neither the constructor argument api_key nor Config.LLM_API_KEY is set. The client wraps the OpenAI SDK, which requires an API key, so construction fails immediately rather than on the first request.","triggerScenarios":"Instantiating LLMClient() in an environment where LLM_API_KEY is unset/empty — missing .env, env var not passed into the container, or config loaded too late.","commonSituations":"Deployments without secrets injected, CI pipelines, local runs after cloning without copying .env.example, or a renamed config key.","solutions":["Set LLM_API_KEY (and check LLM_BASE_URL/LLM_MODEL_NAME while at it) in the environment/config before creating LLMClient","Pass api_key explicitly when the key comes from a secret manager","Validate required config once at application startup and abort with a clear message listing all missing keys"],"exampleFix":"# before\nclient = LLMClient()  # LLM_API_KEY unset -> ValueError\n\n# after\napi_key = os.environ.get(\"LLM_API_KEY\")\nif not api_key:\n    raise SystemExit(\"LLM_API_KEY is required\")\nclient = LLMClient(api_key=api_key)","handlingStrategy":"validation","validationCode":"if not (api_key or Config.LLM_API_KEY):\n    raise SystemExit(\"LLM_API_KEY is required\")","typeGuard":null,"tryCatchPattern":"try:\n    client = LLMClient(api_key=key)\nexcept ValueError as e:\n    logger.error(\"config error: %s\", e)\n    raise","preventionTips":["Centralize required-config validation at boot and fail fast","Document required env vars in .env.example / README","Use a secret manager; never commit keys"],"tags":["configuration","llm","api-key","startup"],"backgroundTag":null,"analyzedSha":"b5b53acc57189a4a42e44a23e149dc655c98fe82","analyzedAt":"2026-08-14T22:29:33.146Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}