{"record":{"id":"d18135191fef7c83","repo":"FoundationAgents/MetaGPT","slug":"code-resp-code-request-id-resp-request-id","errorCode":null,"errorMessage":"code: {resp.code}, request_id: {resp.request_id}, message: {resp.message}","messagePattern":"code: (.+?), request_id: (.+?), message: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"metagpt/provider/dashscope_api.py","lineNumber":198,"sourceCode":"\n    def _const_kwargs(self, messages: list[dict], stream: bool = False) -> dict:\n        kwargs = {\n            \"api_key\": self.api_key,\n            \"model\": self.model,\n            \"messages\": messages,\n            \"stream\": stream,\n            \"result_format\": \"message\",\n        }\n        if self.config.temperature > 0:\n            # different model has default temperature. only set when it\"s specified.\n            kwargs[\"temperature\"] = self.config.temperature\n        if stream:\n            kwargs[\"incremental_output\"] = True\n        return kwargs\n\n    def _check_response(self, resp: GenerationResponse):\n        if resp.status_code != HTTPStatus.OK:\n            raise RuntimeError(f\"code: {resp.code}, request_id: {resp.request_id}, message: {resp.message}\")\n\n    def get_choice_text(self, output: GenerationOutput) -> str:\n        return output.get(\"choices\", [{}])[0].get(\"message\", {}).get(\"content\", \"\")\n\n    def completion(self, messages: list[dict]) -> GenerationOutput:\n        resp: GenerationResponse = self.aclient.call(**self._const_kwargs(messages, stream=False))\n        self._check_response(resp)\n\n        self._update_costs(dict(resp.usage))\n        return resp.output\n\n    async def _achat_completion(self, messages: list[dict], timeout: int = USE_CONFIG_TIMEOUT) -> GenerationOutput:\n        resp: GenerationResponse = await self.aclient.acall(**self._const_kwargs(messages, stream=False))\n        self._check_response(resp)\n        self._update_costs(dict(resp.usage))\n        return resp.output\n\n    async def acompletion(self, messages: list[dict], timeout=USE_CONFIG_TIMEOUT) -> GenerationOutput:","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/FoundationAgents/MetaGPT/blob/11cdf466d042aece04fc6cfd13b28e1a70341b1f/metagpt/provider/dashscope_api.py#L180-L216","documentation":"After every DashScope call (streaming and non-streaming), _check_response inspects the GenerationResponse; a status_code != 200 raises RuntimeError embedding the DashScope error code, request_id, and server message. This is the surface where all DashScope server-side errors (auth, rate limit, quota, invalid parameter) appear.","triggerScenarios":"Invalid or expired DASHSCOPE_API_KEY (code 401/InvalidApiKey); throttling/code 429 rate limits; quota exhaustion; invalid model name or parameters rejected by the service; any non-OK HTTP status on the generation call.","commonSituations":"Missing/expired API key in env; free-tier quota exhausted; bursts of requests during batch runs hitting TPS limits; using a model id the account/region cannot access.","solutions":["Match on resp code in the message: 401/InvalidApiKey -> fix DASHSCOPE_API_KEY; 429/Throttling -> back off and retry; quota -> upgrade/wait.","Quote the request_id from the message when contacting DashScope support — it identifies the exact call.","Wrap calls with exponential-backoff retry on throttling errors.","Confirm the model id is valid for your account and region."],"exampleFix":"// before\nresp = await llm.acompletion(messages)  # RuntimeError: code: Throttling, ...\n\n// after\nimport asyncio\nfrom metagpt.provider.dashscope_api import Generation\n\nasync def call_with_retry(messages, tries=3):\n    for i in range(tries):\n        try:\n            return await llm.acompletion(messages)\n        except RuntimeError as e:\n            if \"Throttling\" in str(e) and i < tries - 1:\n                await asyncio.sleep(2 ** i)\n                continue\n            raise","handlingStrategy":"retry","validationCode":"# no client-side pre-check can validate server status; validate cheap preconditions only\ndef dashscope_preconditions_ok(api_key: str, model: str) -> bool:\n    return bool(api_key) and bool(model)","typeGuard":null,"tryCatchPattern":"import asyncio, re\n\nTRANSIENT = (\"Throttling\", \"Timeout\", \"ServiceUnavailable\", \"InternalError\")\n\nasync def dashscope_call_with_retry(fn, *args, tries=4, base=1.0, **kwargs):\n    for i in range(tries):\n        try:\n            return await fn(*args, **kwargs)\n        except RuntimeError as e:\n            msg = str(e)\n            if any(t in msg for t in TRANSIENT) and i < tries - 1:\n                await asyncio.sleep(base * 2 ** i)\n                continue\n            if \"InvalidApiKey\" in msg or \"401\" in msg:\n                raise RuntimeError(\"DASHSCOPE_API_KEY invalid or expired\") from e\n            raise\n","preventionTips":["Set DASHSCOPE_API_KEY in the environment and verify it at startup with a minimal call.","Apply exponential backoff for throttling (code 429) and keep request_id for support tickets.","Monitor quota and set concurrency limits below your DashScope tier's TPS."],"tags":["dashscope","api-error","rate-limit","retry"],"backgroundTag":null,"analyzedSha":"11cdf466d042aece04fc6cfd13b28e1a70341b1f","analyzedAt":"2026-08-14T23:20:02.994Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}