FoundationAgents/MetaGPT · error · RuntimeError

code: {resp.code}, request_id: {resp.request_id}, message: {

Error message

code: {resp.code}, request_id: {resp.request_id}, message: {resp.message}

What it means

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.

Source

Thrown at metagpt/provider/dashscope_api.py:198

    def _const_kwargs(self, messages: list[dict], stream: bool = False) -> dict:
        kwargs = {
            "api_key": self.api_key,
            "model": self.model,
            "messages": messages,
            "stream": stream,
            "result_format": "message",
        }
        if self.config.temperature > 0:
            # different model has default temperature. only set when it"s specified.
            kwargs["temperature"] = self.config.temperature
        if stream:
            kwargs["incremental_output"] = True
        return kwargs

    def _check_response(self, resp: GenerationResponse):
        if resp.status_code != HTTPStatus.OK:
            raise RuntimeError(f"code: {resp.code}, request_id: {resp.request_id}, message: {resp.message}")

    def get_choice_text(self, output: GenerationOutput) -> str:
        return output.get("choices", [{}])[0].get("message", {}).get("content", "")

    def completion(self, messages: list[dict]) -> GenerationOutput:
        resp: GenerationResponse = self.aclient.call(**self._const_kwargs(messages, stream=False))
        self._check_response(resp)

        self._update_costs(dict(resp.usage))
        return resp.output

    async def _achat_completion(self, messages: list[dict], timeout: int = USE_CONFIG_TIMEOUT) -> GenerationOutput:
        resp: GenerationResponse = await self.aclient.acall(**self._const_kwargs(messages, stream=False))
        self._check_response(resp)
        self._update_costs(dict(resp.usage))
        return resp.output

    async def acompletion(self, messages: list[dict], timeout=USE_CONFIG_TIMEOUT) -> GenerationOutput:

View on GitHub (pinned to 11cdf466d0)

Solutions

  1. Match on resp code in the message: 401/InvalidApiKey -> fix DASHSCOPE_API_KEY; 429/Throttling -> back off and retry; quota -> upgrade/wait.
  2. Quote the request_id from the message when contacting DashScope support — it identifies the exact call.
  3. Wrap calls with exponential-backoff retry on throttling errors.
  4. Confirm the model id is valid for your account and region.

Example fix

// before
resp = await llm.acompletion(messages)  # RuntimeError: code: Throttling, ...

// after
import asyncio
from metagpt.provider.dashscope_api import Generation

async def call_with_retry(messages, tries=3):
    for i in range(tries):
        try:
            return await llm.acompletion(messages)
        except RuntimeError as e:
            if "Throttling" in str(e) and i < tries - 1:
                await asyncio.sleep(2 ** i)
                continue
            raise
Defensive patterns

Strategy: retry

Validate before calling

# no client-side pre-check can validate server status; validate cheap preconditions only
def dashscope_preconditions_ok(api_key: str, model: str) -> bool:
    return bool(api_key) and bool(model)

Try / catch

import asyncio, re

TRANSIENT = ("Throttling", "Timeout", "ServiceUnavailable", "InternalError")

async def dashscope_call_with_retry(fn, *args, tries=4, base=1.0, **kwargs):
    for i in range(tries):
        try:
            return await fn(*args, **kwargs)
        except RuntimeError as e:
            msg = str(e)
            if any(t in msg for t in TRANSIENT) and i < tries - 1:
                await asyncio.sleep(base * 2 ** i)
                continue
            if "InvalidApiKey" in msg or "401" in msg:
                raise RuntimeError("DASHSCOPE_API_KEY invalid or expired") from e
            raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of FoundationAgents/MetaGPT@11cdf466d0 (2026-08-14). Data as JSON: /api/errors/d18135191fef7c83. Report an issue: GitHub.