{"record":{"id":"e83aa0969817259f","repo":"datawhalechina/hello-agents","slug":"llm-client-is-not-configured-check-env","errorCode":null,"errorMessage":"LLM client is not configured. Check .env.","messagePattern":"LLM client is not configured\\. Check \\.env\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"critical","filePath":"Co-creation-projects/huailishang-AgentPlatformBase/agents/rss_digest/src/rss_digest/llm.py","lineNumber":22,"sourceCode":"from urllib.request import Request, urlopen\nimport json\nimport re\n\n\n@dataclass(slots=True)\nclass LLMClient:\n    model_name: str\n    api_key: str\n    base_url: str\n    timeout_seconds: int\n    json_mode: bool = True\n\n    def is_enabled(self) -> bool:\n        return bool(self.model_name and self.api_key and self.base_url)\n\n    def chat(self, system_prompt: str, user_prompt: str) -> str:\n        if not self.is_enabled():\n            raise RuntimeError(\"LLM client is not configured. Check .env.\")\n\n        payload = {\n            \"model\": self.model_name,\n            \"temperature\": 0.2,\n            \"messages\": [\n                {\"role\": \"system\", \"content\": system_prompt},\n                {\"role\": \"user\", \"content\": user_prompt},\n            ],\n        }\n        if self.json_mode:\n            payload[\"response_format\"] = {\"type\": \"json_object\"}\n\n        body = json.dumps(payload).encode(\"utf-8\")\n        request = Request(\n            f\"{self.base_url}/chat/completions\",\n            data=body,\n            headers={\n                \"Authorization\": f\"Bearer {self.api_key}\",","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/huailishang-AgentPlatformBase/agents/rss_digest/src/rss_digest/llm.py#L4-L40","documentation":"LLMClient.chat raises RuntimeError when the client is not fully configured — model_name, api_key, and base_url must all be truthy per is_enabled(). It is a fail-fast guard so the code never sends a chat request destined to be rejected by the provider.","triggerScenarios":"Calling chat() when any of LLM_MODEL / API key / base URL was never set — typically because the .env file is missing, not loaded, or the variable names don't match what the settings loader expects.","commonSituations":"Deploying without copying .env.example to .env; running in Docker/CI where .env is not copied into the image; pydantic-settings BaseSettings not pointed at the .env path; renaming env vars between environments.","solutions":["Create/fix .env with all three values the client reads (model name, API key, base URL) and ensure it is loaded at startup.","Verify with a quick check: print/app-log client.is_enabled() before first use, or `env | grep -i llm` in the deploy shell.","In Docker/CI, pass the variables as environment variables or explicitly COPY .env in the Dockerfile.","If configuration is genuinely optional, gate chat() calls behind is_enabled() and skip LLM-backed features."],"exampleFix":"# before\nsummary = client.chat(system, user)  # RuntimeError if .env missing\n\n# after\nif not client.is_enabled():\n    raise RuntimeError(\"LLM disabled: set model/API key/base URL in .env before enabling digests\")\nsummary = client.chat(system, user)","handlingStrategy":"validation","validationCode":"if not client.is_enabled():\n    raise SystemExit(\"LLM client incomplete: set model, API key, and base URL in .env\")\nresult = client.chat(system_prompt, user_prompt)","typeGuard":"def llm_ready(client: LLMClient) -> bool:\n    return client.is_enabled()  # model_name and api_key and base_url all set","tryCatchPattern":"try:\n    reply = client.chat(system_prompt, user_prompt)\nexcept RuntimeError as e:\n    if \"not configured\" in str(e):\n        logger.error(\"LLM config missing; digest generation skipped\")\n        return  # feature-flag style skip\n    raise","preventionTips":["Fail fast at startup: assert is_enabled() before entering the digest loop.","Validate .env keys with a preflight check listing all missing variables.","Add a config smoke test (is_enabled) to CI."],"tags":["configuration","env-vars","llm-client","python"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}