fix(relay): record Responses API stream errors - #6549
Conversation
WalkthroughThe OpenAI responses streaming DTO now carries raw error payloads. The stream handler recognizes error and failed response events, resolves nested error data when needed, and reports valid errors through the stream scanner. ChangesOpenAI response error propagation
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@relaykit/dto/openai_response.go`:
- Line 389: The Responses API stream error handling must support top-level error
event fields instead of only nested response.error payloads. In
relaykit/dto/openai_response.go, extend the response DTO around Error with
top-level code, message, and param fields or an equivalent raw fallback; in
relay/channel/openai/relay_responses.go, update the stream response handling to
construct streamError from those top-level values before calling sr.Error(...),
while preserving nested-error handling.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 25f584cf-ef3e-4a34-808b-e8dbb5b58b63
📒 Files selected for processing (2)
relay/channel/openai/relay_responses.gorelaykit/dto/openai_response.go
| type ResponsesStreamResponse struct { | ||
| Type string `json:"type"` | ||
| Response *OpenAIResponsesResponse `json:"response,omitempty"` | ||
| Error json.RawMessage `json:"error,omitempty"` |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== files =="
git ls-files | rg '(^|/)openai_response\.go$|(^|/)relay_responses\.go$|expr\.md$|common/json\.go$' || true
echo
echo "== dto outline =="
ast-grep outline relaykit/dto/openai_response.go --view expanded | sed -n '1,220p' || true
echo
echo "== dto relevant lines =="
sed -n '340,410p' relaykit/dto/openai_response.go
echo
echo "== relay handler relevant lines =="
sed -n '70,130p' relay/channel/openai/relay_responses.go
echo
echo "== references to streamResponse.Error and Response.Error =="
rg -n "streamResponse\.Error|Response\.Error|type.*error|response\.error|Error.*struct|type.*Response" relaykit relay -g '*.go' | sed -n '1,220p'Repository: QuantumNous/new-api
Length of output: 43863
🌐 Web query:
OpenAI Responses streaming top-level error event code message param documentation
💡 Result:
When using streaming with the OpenAI API, error handling occurs both at the initiation of the request and during the stream itself. Error Structure When an API error occurs, the error object consistently includes the following fields [1][2][3]: - code: A string identifying the specific type of error (e.g., 'rate_limit_exceeded', 'invalid_request_error') [4][1][5]. - message: A human-readable string explaining the error [4][1][2]. - param: A string identifying the specific parameter that caused the error, if applicable [4][1][2]. - type: A string categorizing the error (e.g., 'invalid_request_error', 'server_error') [1][2][5]. Streaming Error Handling 1. Request Initiation: Errors that occur before the stream begins (e.g., network issues, authentication errors, or invalid initial parameters) are thrown by the initial API call [6]. These should be caught using standard try-catch blocks surrounding the request initiation [7][8][6]. 2. Streaming Events: For streaming endpoints, such as the Responses API or Chat Completions, the API can emit dedicated error events during the stream [9][4][10]. - In the Responses API, an event with the type 'error' is explicitly emitted when a response fails [4]. This event contains the code, message, and param fields [4]. - If using the OpenAI SDKs, errors during iteration should be caught within the loop that processes the stream chunks [6]. If a stream is interrupted or fails to produce a valid response, the SDK may throw an internal error (e.g., 'OpenAIError') that also requires handling [11][12]. Best Practices - Wrap your request in a try-catch block to handle initial setup errors [7][6]. - When iterating through the stream, be prepared to catch exceptions that may occur due to connection drops or premature stream termination [6][12]. - Consult the official API reference for your specific endpoint, as streaming event schemas can vary between legacy and newer (e.g., Responses) APIs [9][4][10].
Citations:
- 1: https://github.com/openai/openai-python/blob/main/src/openai/_exceptions.py
- 2: https://github.com/openai/openai-deno-build/blob/main/error.ts
- 3: https://app.unpkg.com/openai@6.49.0/files/src/core/error.ts
- 4: https://developers.openai.com/api/reference/resources/responses/streaming-events/
- 5: https://community.openai.com/t/error-code-for-openai-chat-completion/1102402
- 6: Stream handling does not recognize stream errors openai/openai-node#537
- 7: https://developers.openai.com/api/docs/guides/error-codes
- 8: https://learn.microsoft.com/en-gb/answers/questions/1329414/how-can-i-handle-openai-api-errors-when-im-using-t
- 9: https://developers.openai.com/api/docs/guides/streaming-responses
- 10: https://developers.openai.com/api/reference/resources/chat/subresources/completions/streaming-events
- 11: https://github.com/openai/openai-node/blob/master/src/lib/responses/ResponseStream.ts
- 12: on('error', () => ...) event does not fire on "OpenAIError: stream ended without producing a ChatCompletionMessage with role=assistant" openai/openai-node#553
🌐 Web query:
OpenAI Responses streaming response.error event schema top-level error
💡 Result:
In OpenAI streaming responses—particularly within the Responses API and structured streaming contexts—the error event follows a specific schema designed to communicate failure states mid-stream [1][2]. The standard schema for an error event in these streams is structured as follows [1][3]: { "type": "error", "sequence_number": , "error": { "type": "", "code": "<string|null>", "message": "", "param": "<string|object|null>" } } Key components include: type: Always set to "error" to identify the event type [1]. sequence_number: An integer representing the sequence position of the event [1]. error: An object containing the details of the failure [1][3]: - type: The category or classification of the error (e.g., "invalid_request_error", "server_error") [3]. - code: A specific error code string, or null if not applicable [1][3]. - message: A human-readable description of the error [1][3]. - param: The specific parameter associated with the error, which may be a string or an object depending on the error context [1][3]. It is important to distinguish this specific "error" event schema from general API errors, which may be raised by the SDK as exceptions (e.g., APIError, BadRequestError) when the request itself fails before or during the stream [4][5][6]. When using official SDKs, you can typically listen for these events via event emitters or stream iterators (e.g., event.type == "error" or.on("error",...)) to handle terminal states gracefully [2][7][8].
Citations:
- 1: https://developers.openai.com/api/reference/resources/responses/streaming-events
- 2: https://developers.openai.com/api/docs/guides/streaming-responses
- 3: [BUG] StreamingResponseErrorUpdate incorrectly parses error from OpenAI when using a MCP Tool openai/openai-dotnet#528
- 4: https://deepwiki.com/openai/openai-python/4.1.2-streaming-chat-completions
- 5: https://developers.openai.com/api/docs/guides/error-codes
- 6: https://github.com/openai/openai-python/blob/f16fbbd2/src/openai/_exceptions.py
- 7: https://developers.openai.com/api/docs/guides/structured-outputs
- 8: on('error', () => ...) event does not fire on "OpenAIError: stream ended without producing a ChatCompletionMessage with role=assistant" openai/openai-node#553
🌐 Web query:
site:platform.openai.com Responses streaming events "error" code message param
💡 Result:
In the context of OpenAI APIs and general streaming (Server-Sent Events) architectures, errors occurring after a stream has already begun are typically handled by sending a specific error event before closing the connection [1]. For APIs following the OpenAI standard, errors in asynchronous or streaming contexts are structured as objects containing a code and a message [2]. Specifically: 1. Error Structure: Error objects typically consist of a code (a machine-readable string like server_error or rate_limit_exceeded) and a message (a human-readable description of the error) [2]. 2. Streaming Behavior: When a streaming request fails, the server often sends an event containing the error details in the data field—or occasionally terminates the stream abruptly after the final chunk—depending on the specific endpoint's implementation [1]. If you are developing your own streaming API and need to convey errors, it is recommended practice to: - Use the data field of the SSE event to send a JSON-encoded object [1]. - Include a specific type field (e.g., error) to distinguish it from data chunks [1]. - Structure the payload with code and message parameters to ensure consistent error handling for your clients [2]. Always verify the specific implementation details in your API's schema or documentation, as error reporting can vary significantly between different streaming protocols and individual service designs [2][1].
Citations:
- 1: https://platform.openai.com/docs/static/api-definition.yaml
- 2: https://platform.openai.com/docs/api-reference/run-steps/getRunStep
🌐 Web query:
developers.openai.com resource reference responses streaming error code message param
💡 Result:
When streaming responses from the OpenAI API, error events are communicated through specific event types. According to the official documentation for the Responses API, an error event is indicated by the type: "error" property [1][2]. The expected structure for an error event includes the following parameters [1][2]: - code: A string representing the specific error code [1][2]. - message: A string containing the error message [1][2]. - param: A string identifying the parameter that caused the error, if applicable [1][2]. - sequence_number: A number indicating the sequence of the event [1][2]. However, developers have observed that the actual API response may sometimes return these details nested within an error object (e.g., { "type": "error", "error": { "code": "...", "message": "...", "param": "..." } }) rather than at the root level as initially documented [3]. If you encounter difficulty accessing these fields, it is recommended to inspect the raw response or the Patch object (in some SDKs) to retrieve them from the nested structure [3]. When handling streaming in your application, you should listen for the error event type to identify and handle these issues programmatically [4]. Additionally, for non-streaming requests or general API interaction, the API typically returns standard error objects containing code, message, type, and param fields [5][6]. If you are using the OpenAI Python SDK, it generally maps these error responses into specific exception classes (such as RateLimitError or APIError) by parsing the JSON response body [7][6].
Citations:
- 1: https://developers.openai.com/api/reference/resources/responses/streaming-events/
- 2: https://developers.openai.com/api/reference/resources/responses/streaming-events
- 3: [BUG] Streaming Error Event Format Mismatch openai/openai-dotnet#881
- 4: https://developers.openai.com/api/docs/guides/streaming-responses
- 5: https://developers.openai.com/api/docs/guides/error-codes
- 6: https://github.com/openai/openai-python/blob/f16fbbd2/src/openai/_exceptions.py
- 7: https://github.com/openai/openai-python/blob/5e8f09c2/src/openai/_streaming.py
🌐 Web query:
OpenAI Responses API streaming events error event structure code message param type object
💡 Result:
In the OpenAI Responses API, the streaming error event is a specific event type emitted when an error occurs during the stream [1][2]. The documented structure for an error event is as follows [1][3]: { "type": "error", "code": "string", "message": "string", "param": "string", "sequence_number": number } Field details: - type: Always set to "error" [1][3]. - code: A string representing the error code [1][3]. - message: A string containing the error message [1][3]. - param: An optional string indicating the error parameter, if applicable [1][3]. - sequence_number: A number representing the sequence number of this event [1][3]. Note: There have been reports that the API service may intermittently return a nested error structure (e.g., {"error": {"code": "...", "message": "...",...}}) [4][5], which differs from the documented top-level format. Developers should implement robust parsing that can handle both the documented format and, if necessary, the nested structure [5]. Additionally, the Responses API also utilizes a response.failed event for when a response generation specifically fails, which includes the response object itself [1][6]. This should not be confused with the general transport or stream-level error event [6].
Citations:
- 1: https://developers.openai.com/api/reference/resources/responses/streaming-events/
- 2: https://developers.openai.com/api/docs/guides/streaming-responses
- 3: https://developers.openai.com/api/reference/resources/responses/streaming-events
- 4: [BUG] Streaming Error Event Format Mismatch openai/openai-dotnet#881
- 5: Responses API error handling reads error.message, but spec says message is top-level openai/openai-python#2487
- 6: https://community.openai.com/t/responses-api-streaming-the-simple-guide-to-events/1363122
Handle the top-level Responses API error event payload.
type: "error" stream events can carry top-level code, message, and param, so the current streamResponse.Error fallback only handles nested response.*error payloads. Add fields/raw fallback for top-level error events and construct streamError from them before calling sr.Error(...).
📍 Affects 2 files
relaykit/dto/openai_response.go#L389-L389(this comment)relay/channel/openai/relay_responses.go#L99-L109
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@relaykit/dto/openai_response.go` at line 389, The Responses API stream error
handling must support top-level error event fields instead of only nested
response.error payloads. In relaykit/dto/openai_response.go, extend the response
DTO around Error with top-level code, message, and param fields or an equivalent
raw fallback; in relay/channel/openai/relay_responses.go, update the stream
response handling to construct streamError from those top-level values before
calling sr.Error(...), while preserving nested-error handling.
Source: MCP tools
Important
📝 变更描述 / Description
(简述:做了什么?为什么这样改能生效?请基于你对代码逻辑的理解来写,避免粘贴未经整理的内容)
记录 /v1/responses SSE下的error
🚀 变更类型 / Type of change
🔗 关联任务 / Related Issue
✅ 提交前检查项 / Checklist
Bug fix,我已提交或关联对应 Issue,且不会将设计取舍、预期不一致或理解偏差直接归类为 bug。📸 运行证明 / Proof of Work
(请在此粘贴截图、关键日志或测试报告,以证明变更生效)
Summary by CodeRabbit