Skip to content

[OpenCode Go] deepseek-v4-pro via Responses API: 400 tools[N].function missing field 'name' (web_search tool rejected) #42090

Closed as not planned

Description

@Seegin

Summary

deepseek-v4-pro via OpenCode Go (https://opencode.ai/zen/go/v1, Responses API) returns HTTP 400 from Codex:

Error from provider (Console Go): Upstream request failed: [invalid_request_error] Failed to deserialize the JSON body into the target type: tools[8].function: missing field `name`

The same setup works with deepseek-v4-flash, and works with deepseek-v4-pro when using the DeepSeek official API directly.

Environment

  • Client: OpenAI Codex CLI 0.147.0 (wire_api = responses)
  • Provider base URL: https://opencode.ai/zen/go/v1
  • Model: deepseek-v4-pro
  • Reasoning effort: high / max

Root cause (confirmed by capturing the actual request)

I captured the exact request body sent by Codex through a local proxy. tools[8] is:

{"type": "web_search", "external_web_access": {...}}

Per the OpenAI Responses API spec, a web_search tool is a non-function tool and has no name field. The Console Go upstream appears to parse every tool as a function tool and requires function.name, hence:

tools[8].function: missing field `name`

This is the same root cause described in PR #40210 ("toOaCompatibleRequest mapped every tool into {"type":"function","function":{...}}, producing an undefined name that upstream serde rejects ... 400ing the whole request"). It seems that fix is not yet effective on the /v1/responses path for deepseek-v4-pro (tested 2026-08-13, still 400).

Expected behavior

Non-function tools such as web_search should either be accepted as-is (with no function.name requirement) or filtered out when converting to the upstream chat-completions format, while function tools keep their nested function.name (as PR #40210 states).

Repro

  1. Configure Codex with model = "deepseek-v4-pro", base_url = "https://opencode.ai/zen/go/v1", wire_api = "responses".
  2. Run any tool-enabled request (e.g. codex exec "Reply OK").
  3. Observe the 400 above. Flash model on the same config succeeds.

Related

Activity

  1. Seegin commented on Aug 12, 2026

    @Seegin
    Author

    Quick follow-up that might save some time. I ran an extra check after filing this: model name casing is not what triggers it. Codex sends the all-lowercase id deepseek-v4-pro, and that id works fine without tools (200 OK) while still failing as soon as the web_search tool is included. Trying DeepSeek-V4-Pro or DeepSeek V4 Pro gives a completely different error (401 Model ... is not supported), so this really is about tool handling, not the model id.

  2. hairyf commented on Aug 13, 2026

    @hairyf

    Same environment here — Windows, Codex with wire_api = "responses" pointed at https://opencode.ai/zen/go/v1, model deepseek-v4-pro.

    Reproduced the exact tools[N].function: missing field 'name'. The rejected entries are Codex's tool_search (deferred MCP tool discovery) and web_search, which are OpenAI-native tool types that carry no name field — the gateway tries to parse every entry as a function tool and bails. deepseek-v4-flash works because it goes through a different validation path.

    Workaround I'm using: a local proxy that drops nameless tools before forwarding (and additionally normalizes the gateway's non-standard /responses SSE stream, which otherwise makes Codex render empty replies): https://github.com/hairyf/codex-deepseek-subagent-proxy

    Ideally the gateway would skip unknown tool types instead of rejecting the whole request. Happy to share request captures if useful.

  3. TheRainstorm commented on Aug 13, 2026

    @TheRainstorm

    Same problem here: Codex CLI 0.147.0 + deepseek-v4-pro via OpenCode Go (https://opencode.ai/zen/go/v1, wire_api = responses).

    Error from provider (Console Go): Upstream request failed: [invalid_request_error] Failed to deserialize the JSON body into the target type: tools[19].function: missing field `name`
    

    In my case the offending tool is at index 19 — I captured the actual request body through a local proxy and confirmed it is the non-function web_search tool ({"type":"web_search","external_web_access":false}, no name field per the Responses API spec). The exact same setup with deepseek-v4-flash works fine.

  4. Twelveeee commented on Aug 13, 2026

    @Twelveeee

    Confirmed independently with the same issue.
    Environment

     - Codex CLI: 0.147.0
     - Model: deepseek-v4-pro
     - Wire API: responses
     - Provider: OpenCode Go
     - OS: Linux
     Error
    
     text
     Error from provider (Console Go): Upstream request failed:
     [invalid_request_error] Failed to deserialize the JSON body into the target type:
     tools[10].function: missing field name at line 1 column 14153
    
     A/B comparison
    
     - Official DeepSeek API with the same Codex configuration and tool set: works normally
     - OpenCode Go with deepseek-v4-pro: fails on the first turn
    
     The tool index is tools[10] in my environment rather than tools[8], presumably because of a different local tool/MCP ordering. Otherwise, the error signature and behavior are identical.
    
     This confirms that the issue is reproducible across different accounts/environments and appears specific to the OpenCode Go routing or tool-conversion path for deepseek-v4-pro.
    
  5. Seegin commented on Aug 13, 2026

    @Seegin
    Author

    Update: the DeepSeek-specific symptom no longer reproduces, but I am leaving this open on purpose.

    What changed: OpenCode Go moved deepseek-v4-pro (and deepseek-v4-flash) from /v1/responses to /v1/chat/completions; see https://dev.opencode.ai/docs/go/. With wire_api = "chat" the tools[N].function: missing field 'name' 400 no longer occurs, because the Responses->Chat conversion path is bypassed for these models.

    However, this is a routing workaround, not a fix for the underlying bug described here. The web_search-without-name conversion issue on the Responses path is still unresolved and is tracked by PR #40210 (still open). Any model that still goes through the Responses conversion can hit the same error.

    I would rather keep this open until #40210 lands, or have a maintainer close it explicitly as "endpoint migrated, root cause tracked in #40210". Closing it now as simply "resolved" would hide that the Responses conversion bug remains.

  6. gx9633-dev commented on Aug 13, 2026

    @gx9633-dev

    Same issue here — Codex Desktop user hitting Console Go via a third-party relay (wire_api = responses), deepseek-v4-pro.

    Additional data points from my side (2026-08-13):

    • 13 failed sessions (8/11 ×6, 8/13 ×7), all deepseek-v4-pro. Identical config on deepseek-v4-flash: zero errors all of 8/12 and 8/13 morning.
    • The failing index drifts (23/24/25/26) with the tool count. In my captured failure body web_search sits at tools[26]: an extra tool (list_available_plugins_to_install) pushed it one position past the working request (26 tools, web_search at index 25).
    • Replayed with a real key today: pro now returns 503 "Endpoint is unavailable" on the /v1/responses path, while flash replays return 200 — same 503 pattern reported in opencode-go (Console Go) provider returns 400/401/500 for subscribed models #37056.
    • PR fix(console): emit complete Responses-API SSE lifecycle for converted streams #40210's fix (drop non-function tools in toOaCompatibleRequest) does not appear effective on the pro /v1/responses path as of 2026-08-13.

    Happy to attach sanitized request bodies (27-tool failing vs 26-tool working) if that helps.

  7. tututuhehehe commented on Aug 14, 2026

    @tututuhehehe

    Reproduces outside Codex too, and on flash, not just v4-pro: Grok Build's web_search tool makes a non-streaming POST /v1/responses call with tools: [{type: "web_search"}] against https://opencode.ai/zen/go/v1 (BYOK, deepseek-v4-flash). The response fails to deserialize in the client with:

    Failed to parse response: missing field `query`
    

    So the search tool errors on every call (the agent then falls back to other search methods). For comparison, the same request against the DeepSeek official API (https://api.deepseek.com/responses, deepseek-v4-flash) succeeds end-to-end — which points to the zen/go conversion layer being the inconsistent part, not the upstream provider.

    This looks like the same family of bug as #40171 / PR #40210: the /v1/responses path on zen/go doesn't round-trip the OpenAI Responses shapes faithfully (missing/renamed fields, incomplete SSE lifecycle).

  8. shukebeta commented on Aug 14, 2026

    @shukebeta

    Same root cause also hits the free Console tier (/zen/v1), so this is broader than pro-on-Go.

    • Client: Codex CLI 0.147.0 (wire_api = responses), base https://opencode.ai/zen/v1, model deepseek-v4-flash-free
    • Error: Error from provider (Console): Upstream request failed: [400] 1 validation error: {'type': 'missing', 'loc': ('body', 'tools', 9, 'function', 'name'), ...} — sglang upstream, POST /v1/chat/completions
    • Same config pointed at /zen/go/v1 + deepseek-v4-flash succeeds.
    • Chat/completions format with the same tools against /zen/v1 + deepseek-v4-flash-free passes schema validation and only hits the free-tier rate limit (429) — so the tools themselves are accepted; only the responses→chat-completions conversion breaks.

    Matches the captured root cause here: the converter mishandles codex's web_search tool (which carries an external_web_access field) and emits {"type":"function","function":{}} with no name. A bare {"type":"web_search"} probe passes, consistent with the fielded shape being the trigger. Worth retitling to cover the free tier as well, since the PR #40210 fix needs to reach the /zen/v1 path too.

  9. github-actions commented on Oct 15, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions