Repository navigation
Description
Description
Summary
When using the OpenAI Responses API (sdk.responses()) with models served through certain OpenAI-compatible gateways, the SSE stream begins with a synthetic chatcmpl-dummy frame in Chat Completions format before the real Responses API events. This frame is not a valid Responses API event and causes a TypeValidationError that terminates the agent turn.
Environment
- OpenCode version: 1.16.0 (dev), 1.15.13 (release)
- Provider: OpenAI (
@ai-sdk/openai) - Model:
gpt-5.5(via OpenAI-compatible gateway) - Runtime:
ai-sdk
Reproducing
1. Verification command
Set up environment variables for your OpenAI-compatible provider:
export OPENAI_BASE_URL="<your-endpoint>/v1"
export OPENAI_API_KEY="<your-api-key>"Run opencode with the Responses API (default) and Chat Completions API:
# Test with gpt-5.5 (Responses API — fails)
opencode run "say hi" --format json --model openai/gpt-5.5 --dangerously-skip-permissions2. gpt-5.5 fails with TypeValidationError
The stream errors immediately:
{
"type": "error",
"error": {
"name": "UnknownError",
"data": {
"message": "Type validation failed: Value: {\"id\":\"chatcmpl-dummy\",\"object\":\"chat.completion.chunk\",\"created\":1780651633,\"model\":\"gpt-5.5\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\"}}]}.\nError message: [\n {\n \"code\": \"invalid_union\",\n \"errors\": [\n [\n {\n \"code\": \"invalid_value\",\n \"values\": [\"response.output_text.delta\"],\n \"path\": [\"type\"],\n \"message\": \"Invalid input: expected \\\"response.output_text.delta\\\"\"\n },\n ...\n ],\n ...\n ],\n \"message\": \"Invalid input\"\n }\n]"
}
}
}The error shows chatcmpl-dummy — a Chat Completions format frame with "content":"" — being passed to the Responses API event validator, which rejects it because it does not match any expected event type (response.output_text.delta, response.created, etc.).
3. deepseek-v4-pro works fine
The same setup works correctly with DeepSeek's native API (which does not go through the same gateway):
opencode run "say hi" --format json --model deepseek/deepseek-v4-pro --dangerously-skip-permissionsExpected output:
{"type":"step_start","part":{"type":"step-start"}}
{"type":"text","part":{"type":"text","text":"hi"}}
{"type":"step_finish","part":{"type":"step-finish"}}4. Root cause confirmed via curl
Probing the Responses API endpoint directly reveals the synthetic frame:
curl -N -s "${OPENAI_BASE_URL}/responses" \
-H "Authorization: Bearer ${OPENAI_API_KEY}" \
-H "Content-Type: application/json" \
-d '{"model":"gpt-5.5","input":"hello","stream":true}'The very first SSE event is:
data: {"id":"chatcmpl-dummy","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant","content":""}}]}
Note the content: "" — this frame carries no actual content. It is a bare data: frame (no event: prefix) with object: "chat.completion.chunk" — it is not a valid Responses API event. The subsequent frames are proper Responses API events (event: response.created, event: response.output_text.delta, etc.).
The same test against DeepSeek's API shows no such frame:
curl -N -s "${DEEPSEEK_BASE_URL}/responses" \
-H "Authorization: Bearer ${DEEPSEEK_API_KEY}" \
-H "Content-Type: application/json" \
-d '{"model":"deepseek-v4-pro","input":"hello","stream":true}'Output starts directly with a proper Responses API event — no chatcmpl-dummy prefix.
5. Suggested fix
The chatcmpl-dummy frame has a hardcoded ID ("chatcmpl-dummy"). The fix is to filter it out at the HTTP response level in the AI SDK's custom fetch wrapper, before the stream reaches the event validator.
Location: packages/opencode/src/provider/provider.ts — in the custom fetch wrapper inside resolveSDK().
Approach: When the response is an SSE stream from a /responses endpoint, pipe the body through a TransformStream that parses each SSE event's data: line as JSON and drops any event whose id equals "chatcmpl-dummy".
This approach:
- Precisely targets only the synthetic
chatcmpl-dummyframe - Does not affect normal Chat Completions or Responses API streams
- Requires no user configuration changes
- Is transparent to all other providers
Plugins
No response
OpenCode version
No response
Steps to reproduce
No response
Screenshot and/or share link
No response
Operating System
No response
Terminal
No response
Activity
rekram1-node commentedon Jun 5, 2026
sounds like ur gateway/proxy has a bug? What gateway/proxy is this
ben-wangz commentedon Jun 6, 2026
I use local sub2api v0.1.125 to manage my accounts. And I do not meet this problem except the gpt model.
ben-wangz commentedon Jun 10, 2026
updating PR fix:
the filtering is now configurable through opencode.json via provider options, for example provider.openai.options.filterSseFrame.
By default, no SSE frames are filtered. The filter only runs when filterSseFrame is explicitly configured, so existing users are unaffected.
github-actions commentedon Aug 10, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.