Repository navigation
Description
Summary
For an OpenAI Responses model that the built-in catalog opts into the WebSocket session transport (here: openai/gpt-5.6-sol), provider-level providers.openai.transport: "http" does not disable it. The session still opens the Responses WebSocket, and when the upstream returns an error event whose error field is a string instead of an object, the step crashes with AI.Error: Invalid OpenAI Responses WebSocket event. Only a model-level transport: "http" works.
Environment
- opencode version: 2.0.4
- OS: Darwin 25.6.0 (arm64)
- Terminal: zed (TERM=xterm-256color, COLORTERM=truecolor)
- Shell: /bin/zsh
- Install/channel: latest, npm
@opencode/cli(opencode/opencode2) - Active plugins: agentsmd-plugin; second internal plugin redacted
Reproduction
-
Configure only the provider-level transport:
// ~/.config/opencode/opencode.jsonc { "model": "openai/gpt-5.6-sol", "providers": { "openai": { "transport": "http" } } }
-
Restart the service so a fresh server loads the config:
opencode service restart -
Run a one-shot session:
opencode run -m openai/gpt-5.6-sol "Reply with exactly: OK"
Expected Behavior
Provider-level transport: "http" disables the WebSocket session transport for all models of that provider, per the providers docs: "transport: \"websocket\" enables a provider or model; \"http\" disables it."
Actual Behavior
The session still uses the OpenAI Responses WebSocket. When the upstream endpoint sends an error event whose error field is a string, the step fails and the server log shows repeated Failed to drain Session:
AI.Error: Invalid OpenAI Responses WebSocket event
[cause]: AI.Error.InvalidProviderOutput: Invalid OpenAI Responses WebSocket event
[cause]: SchemaError: Expected object | null | undefined
at ["error"]
Adding a model-level override makes the identical prompt succeed on the same server:
"providers": {
"openai": {
"transport": "http",
"models": { "gpt-5.6-sol": { "transport": "http" } }
}
}Additional Context
- Consistently reproducible; reproduced after a service restart and in brand-new sessions, so it is not stale server config or pre-existing session state.
- The upstream here is a Responses-compatible gateway that emitted an error frame shaped like
{ "type": "error", "error": "<message>" }(string, not an object). The WS event decoder requireserror: object | null | undefined, so the real upstream error is swallowed and surfaces only asInvalid OpenAI Responses WebSocket event. Worth making the decoder tolerant (or falling back to the raw payload) independently of the transport-precedence issue. - Likely related to the documented rule "a model value overrides its provider value": if the built-in WebSocket opt-in for a catalog model is stored as a model-level
transport, then a user-set provider-level"http"can never win, which makes the provider-level knob ineffective for exactly the WS-enabled models it exists for. - Workaround: set
transport: "http"on each affected model individually.
Activity