{"record":{"id":"63472912c0adf776","repo":"iflytek/astron-agent","slug":"open-ai-request-error-anthropic-failed","errorCode":"OPEN_AI_REQUEST_ERROR","errorMessage":"Anthropic request failed","messagePattern":"Anthropic request failed","errorType":"error_code","errorClass":"CustomException","httpStatus":null,"severity":"error","filePath":"core/workflow/infra/providers/llm/anthropic/anthropic_chat_llm.py","lineNumber":246,"sourceCode":"                    \"total_tokens\": input_tokens + output_tokens,\n                },\n            }\n\n        # Message stop event - signals end of stream\n        elif isinstance(event, RawMessageStopEvent):\n            return {\n                \"choices\": [\n                    {\n                        \"delta\": {\"content\": \"\", \"reasoning_content\": \"\"},\n                        \"finish_reason\": ChatStatus.FINISH_REASON.value,\n                    }\n                ],\n                \"usage\": usage,\n            }\n\n        # Error event - raise exception\n        elif hasattr(event, \"type\") and \"error\" in event.type:\n            raise CustomException(\n                err_code=CodeEnum.OPEN_AI_REQUEST_ERROR,\n                err_msg=str(getattr(event, \"error\", \"Anthropic request failed\")),\n                cause_error=str(event),\n            )\n        else:\n            # Other event types we don't handle\n            return None\n\n    async def _recv_messages(  # noqa: C901\n        self,\n        url: str,\n        user_message: list,\n        extra_params: dict,\n        span: Span,\n        timeout: float | None = None,\n    ) -> AsyncIterator[LLMResponse]:\n        \"\"\"\n        Receive messages using Anthropic SDK streaming.","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/core/workflow/infra/providers/llm/anthropic/anthropic_chat_llm.py#L228-L264","documentation":"This error is raised inside _normalize_event when a streamed Anthropic SDK event is an error-type event (event.type contains 'error'). The SDK surfaced a server-side error event mid-stream (e.g. an 'error' event in the SSE stream such as overloaded_error or invalid_request_error), and this adapter converts it into a CustomException with code OPEN_AI_REQUEST_ERROR. The message is taken from the event's error attribute, defaulting to 'Anthropic request failed' when the attribute is absent.","triggerScenarios":"The Anthropic messages stream emits an event whose type contains 'error' during _recv_messages consumption — e.g. the API returns an overloaded_error (529), an invalid_request_error mid-stream, or the stream is aborted after starting. It is raised from the event-normalization loop, not from the initial HTTP handshake.","commonSituations":"Anthropic service overload/529s during streaming; sending a parameter the API rejects only after the stream opens (model name typo, too-large max_tokens); proxy/gateway (e.g. a base_url pointed at a compatible endpoint) returning error payloads as stream events; request aborted by content filters or long-running stream termination.","solutions":["Read cause_error in the CustomException to see the exact Anthropic error event (type and message); fix the request parameter it names (model id, max_tokens, malformed message).","If the event is overloaded_error, retry with exponential backoff — it is a transient Anthropic capacity issue, not a client bug.","Verify the model name and parameter values against the Anthropic Messages API for the SDK version in use.","If using a custom base_url (proxy/gateway), confirm the gateway forwards valid Anthropic SSE events and not its own error payloads."],"exampleFix":"// before\nresponse = client.messages.create(model=\"claude-3-5-sonnet-latest\", max_tokens=200000, ...)\n// after (valid model + within context limit)\nresponse = client.messages.create(model=\"claude-3-5-sonnet-20241022\", max_tokens=8192, ...)","handlingStrategy":"try-catch","validationCode":"def validate_request(payload: dict) -> None:\n    assert payload.get(\"model\"), \"model is required\"\n    assert isinstance(payload.get(\"max_tokens\", 0), int) and payload[\"max_tokens\"] > 0, \"max_tokens must be a positive int\"\n    for m in payload.get(\"messages\", []):\n        assert m.get(\"role\") in (\"user\", \"assistant\"), f\"invalid role: {m.get('role')}\"\nvalidate_request(payload)","typeGuard":"def is_error_event(event) -> bool:\n    t = getattr(event, \"type\", \"\") or \"\"\n    return isinstance(t, str) and \"error\" in t","tryCatchPattern":"try:\n    async for resp in llm.achat(messages):\n        yield resp\nexcept CustomException as e:\n    if \"overloaded\" in str(e.cause_error).lower():\n        await asyncio.sleep(backoff); retry()\n    else:\n        logger.error(\"Anthropic stream error: %s\", e.cause_error)\n        raise","preventionTips":["Validate model id and max_tokens against the Messages API schema before sending.","Implement retry-with-backoff for overloaded_error (529), which is transient.","When using a proxy base_url, test that it faithfully relays Anthropic SSE events.","Log the full cause_error to diagnose which stream parameter the API rejected."],"tags":["anthropic","streaming","llm","api-error","retryable"],"backgroundTag":"upstream-api-error","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}