iflytek/astron-agent · error · ClientResponseError
HTTP Error
Error message
HTTP Error: {text} What it means
This aiohttp ClientResponseError is raised by the workflow memory node's _do_request when the remote Memory API returns any HTTP status other than 200. The response body is captured in the error message and logged to the tracing span, so the text usually reveals the upstream failure reason. It wraps the failed HTTP exchange rather than a local bug.
Solutions
- Read the message body (also visible in the span info event 'Memory API HTTP error: <status>:<text>') to identify the upstream status and fix accordingly
- Verify the Memory API URL and auth headers configured for the memory node
- Call the Memory API endpoint directly with curl using the same payload to reproduce and debug
- Add retry logic for transient 5xx statuses and alert on persistent non-200 responses
Example fix
// before
raise aiohttp.ClientResponseError(request_info=response.request_info, history=response.history, status=response.status, message=f"HTTP Error: {text}")
// after
if response.status >= 500 and attempt < max_retries:
await asyncio.sleep(backoff); continue
raise aiohttp.ClientResponseError(request_info=response.request_info, history=response.history, status=response.status, message=f"Memory API returned {response.status}: {text}") Defensive patterns
Strategy: try-catch
Validate before calling
# before calling the node, probe the Memory API health
async def memory_api_reachable(url, headers):
try:
async with aiohttp.ClientSession() as s:
async with s.get(url.rsplit('/', 1)[0] + '/health', headers=headers, timeout=aiohttp.ClientTimeout(total=5)) as r:
return r.status == 200
except aiohttp.ClientError:
return False Try / catch
try:
result = await memory_node.execute(...)
except aiohttp.ClientResponseError as e:
logger.error("memory api failed: status=%s body=%s", e.status, e.message)
raise MemoryUnavailableError(...) from e Prevention
- Health-check the Memory API before running workflows that use memory nodes
- Keep auth tokens fresh and verify the configured base URL after any service redeploy
- Alert on 5xx rates from the Memory API
When it happens
Trigger: execute() calls _do_request, which does session.post(url, headers, json=payload); the server responds with status != 200 (e.g. 401 invalid token, 404 wrong path, 500 backend crash), and the body text is embedded into the raised ClientResponseError.
Common situations: Misconfigured MEMORY_API base URL or path, expired/missing auth token in headers, Memory API deployed with a breaking version change, gateway returning 502/503 during restarts, or payload rejected with 400 due to schema drift.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- CBG_RAGError
- <dynamic request failure: str(err)>
- HTTP Error
- sandbox-exec failed: HTTP
- Skill resource download failed: HTTP
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/7c651670796a9b7b.
Report an issue: GitHub.
Appendix: source
Thrown at core/workflow/engine/nodes/memory/base.py:91
api_secret=os.getenv("MEMORY_AUTH_SECRET", ""),
)
payload = self.build_payload(uid, inputs)
await span.add_info_event_async(f"Memory API Request Payload: {payload}")
headers = {
"Content-Type": "application/json",
"x-appid": self.app_id,
}
session = HttpClient.get_session()
async with session.post(url, headers=headers, json=payload) as response:
if response.status != 200:
text = await response.text()
await span.add_info_event_async(
f"Memory API HTTP error: {response.status}:{text}"
)
raise aiohttp.ClientResponseError(
request_info=response.request_info,
history=response.history,
status=response.status,
message=f"HTTP Error: {text}",
)
raw_data = cast(dict[str, Any], await response.json())
await span.add_info_event_async(f"Memory API Response Data: {raw_data}")
if raw_data.get("code") != 0:
raise CustomException(
CodeEnum.MEMORY_NODE_EXECUTION_ERROR,
f"Memory API Exception: {raw_data.get('code')}: {raw_data.get('message')}",
)
return raw_data
async def execute(
self,
variable_pool: VariablePool,View on GitHub (pinned to 5e758547a8)