FoundationAgents/MetaGPT · error · TimeoutError
Request timed out
Error message
Request timed out
What it means
MetaGPT's async requestor converts aiohttp.ServerTimeoutError or asyncio.TimeoutError raised while reading the (already-received) response body into a plain Python TimeoutError with the message 'Request timed out'. The connect/read timeout that was set on the request (e.g. the provider's timeout config or USE_CONFIG_TIMEOUT) was exceeded during body read, so the call is aborted.
Source
Thrown at metagpt/provider/general_api_requestor.py:128
Returns:
Tuple[Union[OpenAIResponse, AsyncGenerator[OpenAIResponse, None]], bool]: A tuple containing the response content and a boolean indicating if it is a stream.
"""
content_type = result.headers.get("Content-Type", "")
if stream and (
"text/event-stream" in content_type or "application/x-ndjson" in content_type or content_type == ""
):
return (
(
self._interpret_response_line(line, result.status, result.headers, stream=True)
async for line in result.content
),
True,
)
else:
try:
response_content = await result.read()
except (aiohttp.ServerTimeoutError, asyncio.TimeoutError) as e:
raise TimeoutError("Request timed out") from e
except aiohttp.ClientError as exp:
logger.warning(f"response: {result}, exp: {exp}")
response_content = b""
return (
self._interpret_response_line(
response_content, # let the caller decode the msg
result.status,
result.headers,
stream=False,
),
False,
)
View on GitHub (pinned to 11cdf466d0)
Solutions
- Increase the request timeout, e.g. set LLM_API_TIMEOUT (or the provider's timeout argument) to 300+ seconds.
- Use streaming mode (_achat_completion_stream / stream=True) where supported; MetaGPT's default providers often route long completions through streaming for this reason.
- Retry the request with backoff; read timeouts are frequently transient under network congestion.
- Check proxy/network health if timeouts recur across all models.
Example fix
# before await provider._achat_completion(messages, timeout=30) # too short for big outputs # after await provider._achat_completion(messages, timeout=600) # or in config2.yaml: LLM_API_TIMEOUT: 600
Defensive patterns
Strategy: retry
Validate before calling
timeout = provider.get_timeout(USE_CONFIG_TIMEOUT)
if timeout and timeout < 120 and expected_large_output:
timeout = 300 # raise for large completions Try / catch
import asyncio
for attempt in range(3):
try:
rsp = await provider._achat_completion(messages, timeout=600)
break
except TimeoutError:
if attempt == 2:
raise
await asyncio.sleep(2 ** attempt)
# note: aiohttp errors were already wrapped into builtin TimeoutError Prevention
- Set LLM_API_TIMEOUT generously (>= 300s) for long generations
- Prefer streaming mode for big outputs
- Wrap completions in bounded retry with backoff for read timeouts
When it happens
Trigger: Non-streaming async completion (_achat_completion) where the server accepts the request but streams the body too slowly: await result.read() exceeds the configured read timeout; long generations with a small timeout value, or a proxy/network that stalls mid-body.
Common situations: Default timeouts too short for large completions or slow reasoning models, congested corporate proxies, streaming disabled (non-stream path forces a single body read), or LLM_API_TIMEOUT misconfigured in config2.yaml.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
AI-assisted analysis of FoundationAgents/MetaGPT@11cdf466d0 (2026-08-14).
Data as JSON: /api/errors/329d4366fe340243.
Report an issue: GitHub.