Description
When a provider using the Responses streaming path returns a wrapped error chunk such as:
{"error":{"code":"","message":"","type":"server_error"},"request_id":""}
OpenCode currently tries to validate it as a normal response.* stream event and fails with:
Type validation failed
invalid_union
This appears to happen before any terminal event like response.completed / response.incomplete is seen.
That makes the failure behave like a stream protocol failure before terminal event, but it is currently surfaced as a schema/type validation error instead of a retryable API/stream failure.
This is especially problematic for subagents/background tasks: the child stream can die without entering a proper terminal failed/completed state, while the parent keeps waiting for the child response indefinitely.
Based on local investigation:
- the Responses path only treats
response.completed / response.incomplete as terminal
- wrapped error chunks are not normalized before schema validation
- existing retry/backoff is already wired for
APICallError -> MessageV2.APIError -> SessionRetry.retryable()
- plugin hooks can modify request params/headers, but cannot intercept/normalize response stream chunks before validation
So the current behavior seems to be:
- provider sends wrapped error chunk in stream
- chunk is validated as normal
response.* event
- union validation fails (
invalid_union)
- failure does not enter the normal retryable API error path
- parent/subagent waiting logic may never get a proper terminal failure signal
Plugins
oh-my-opencode
OpenCode version
Observed on recent OpenCode builds using the Responses streaming path; local repo analysis was against anomalyco/opencode dev and a local installation that surfaced the bundled stack in the TUI worker.
Steps to reproduce
- Use a provider/model path that goes through the Responses streaming implementation.
- Have the upstream stream return a wrapped error chunk like:
{"error":{"code":"","message":"","type":"server_error"},"request_id":""}
- Observe that OpenCode reports a
Type validation failed / invalid_union error instead of handling it like a retryable stream/API failure.
- In subagent/background-task scenarios, observe that the parent can continue waiting because the child did not complete with a normal terminal event.
Screenshot and/or share link
Example error payload observed locally:
Type validation failed: Value: {"error":{"code":"","message":"","type":"server_error"},"request_id":""}
Error message: invalid_union ...
Operating System
Linux
Terminal
N/A
Expected behavior
Wrapped stream error chunks / premature stream failures before response.completed or response.incomplete should be treated as something like:
stream terminated before terminal event
- or
stream ended without completed response
and then mapped into the existing retry/backoff flow (for example via APICallError with the correct retryability), instead of surfacing as raw schema validation failure.
That would make this behave more like retryable HTTP/provider failures and also ensure parent sessions/subagents receive a proper terminal failure signal.
Suggested direction
For the Responses streaming path:
- skip empty/meta-only frames
- detect wrapped error chunks such as
{ "error": { ... } }
- normalize them before schema validation, or convert them directly into a retryable
APICallError
- if the stream ends without
response.completed / response.incomplete, treat that as a stream termination failure rather than a generic validation error
This would avoid the invalid_union surface error and should also prevent parent agents from waiting forever on failed child streams.
Description
When a provider using the Responses streaming path returns a wrapped error chunk such as:
{"error":{"code":"","message":"","type":"server_error"},"request_id":""}OpenCode currently tries to validate it as a normal
response.*stream event and fails with:Type validation failedinvalid_unionThis appears to happen before any terminal event like
response.completed/response.incompleteis seen.That makes the failure behave like a stream protocol failure before terminal event, but it is currently surfaced as a schema/type validation error instead of a retryable API/stream failure.
This is especially problematic for subagents/background tasks: the child stream can die without entering a proper terminal failed/completed state, while the parent keeps waiting for the child response indefinitely.
Based on local investigation:
response.completed/response.incompleteas terminalAPICallError -> MessageV2.APIError -> SessionRetry.retryable()So the current behavior seems to be:
response.*eventinvalid_union)Plugins
oh-my-opencodeOpenCode version
Observed on recent OpenCode builds using the Responses streaming path; local repo analysis was against
anomalyco/opencodedevand a local installation that surfaced the bundled stack in the TUI worker.Steps to reproduce
{"error":{"code":"","message":"","type":"server_error"},"request_id":""}Type validation failed/invalid_unionerror instead of handling it like a retryable stream/API failure.Screenshot and/or share link
Example error payload observed locally:
Operating System
Linux
Terminal
N/A
Expected behavior
Wrapped stream error chunks / premature stream failures before
response.completedorresponse.incompleteshould be treated as something like:stream terminated before terminal eventstream ended without completed responseand then mapped into the existing retry/backoff flow (for example via
APICallErrorwith the correct retryability), instead of surfacing as raw schema validation failure.That would make this behave more like retryable HTTP/provider failures and also ensure parent sessions/subagents receive a proper terminal failure signal.
Suggested direction
For the Responses streaming path:
{ "error": { ... } }APICallErrorresponse.completed/response.incomplete, treat that as a stream termination failure rather than a generic validation errorThis would avoid the
invalid_unionsurface error and should also prevent parent agents from waiting forever on failed child streams.