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

  1. 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
  2. Verify the Memory API URL and auth headers configured for the memory node
  3. Call the Memory API endpoint directly with curl using the same payload to reproduce and debug
  4. 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

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


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)