Skip to content

Go/Zen gateway: intermittent 400 "reasoning_content must be passed back" for clients that don't replay DeepSeek reasoning (store-miss on call_id) #58064

Open

Description

@sanqiuyef

Summary

Long deepseek-v4.1-flash sessions through the Go/Zen gateway (https://opencode.ai/zen/go/v1) intermittently fail with a non-retryable HTTP 400:

Upstream request failed: [invalid_request_error] The `reasoning_content` in the thinking mode must be passed back to the API.

The trigger is now clear from capture-based testing: the gateway silently auto-replays DeepSeek reasoning from a server-side store keyed by call_id, and when a call_id is not in that store, the request is forwarded to DeepSeek without reasoning and rejected with this 400. Clients that (a) never replay reasoning, or (b) replay history containing tool calls whose reasoning has fallen out of the gateway store, get hard 400s — intermittently, and with frequency that grows with session length. This is the same failure family as #55584 / #48180 / #48093, but with a deterministic minimal repro and the request-side evidence you asked for when closing #55584.

Environment

item value
Client ZCode 3.16.2 (third-party desktop coding agent, ZCode/3.16.2 UA) — sends x-opencode-session per the Go docs
Endpoint https://opencode.ai/zen/go/v1 (both /chat/completions and /responses paths)
Model deepseek-v4.1-flash, reasoning_effort: "max"
OS Windows 10 x64
Observed 2026-10-18 → 2026-10-22; failed turns per day: 1, 0, 1, 3, 6+ (grows with session length)
Example failing requests request ids 53529188…, eb8c94c5…, d7fbd6c2… (104–122 input items, 38–44 function_call items, zero reasoning items, gateway's own call_00_… ids)

Evidence

1. The client never sends reasoning, and the gateway usually compensates. Captured request bodies (client-side rollout logs) contain assistant tool-call turns with no reasoning_content / no reasoning items at all. Most such requests return 200 — so the gateway is injecting the reasoning server-side.

2. Deterministic minimal repro (no account state needed): on POST /zen/go/v1/responses, send an input containing a function_call item whose call_id the gateway has never issued:

// → 400 "The `reasoning_content` in the thinking mode must be passed back to the API." (100%)
{"model":"deepseek-v4.1-flash","stream":false,"tools":[…],
 "input":[{"type":"message","role":"user","content":[{"type":"input_text","text":"hi"}]},
          {"type":"function_call","call_id":"call_abc123","name":"f","arguments":"{}"},
          {"type":"function_call_output","call_id":"call_abc123","output":"x"}]}

Prefixing a synthetic {"type":"reasoning", …} item before the function_call → 200. The same shape with a genuine call_id from a real prior response → 200, even under a different x-opencode-session. So the gateway resolves reasoning by call_id lookup, and unknown/evicted ids surface the raw DeepSeek 400.

3. Identical bodies flakiness = store TTL/eviction. Real sessions fail exactly this way: requests that succeed seconds apart start failing after an idle gap (e.g. the first request of a new turn after a few minutes), and identical-byte replays return 200/400 inconsistently — matching #51201's "identical bytes replay 200/400/200" observation and the sharp onset mid-October reported in #55584 (independent Codex CLI reporter, no proxy, disable_response_storage=true, 0 errors for days → 6 in 16 minutes on 2026-10-16).

4. Why the first-party client doesn't hit this: OpenCode ≥2.0.29 always replays reasoning_content on earlier assistant turns for deepseek* models (empty string when nothing stored — per maintainer comment in #55584). Third-party clients without that workaround have no path that satisfies the upstream.

Expected behavior (any of these would fix it)

  1. Make the gateway-side reasoning store durable (or replay-on-miss), so genuine call_ids never degrade to this 400; or
  2. Return a structured, retryable error (5xx / Retry-After) instead of invalid_request_error 400 when the store misses — a plain replay of the same body succeeds; or
  3. Stop forwarding the strict upstream validation when the gateway knows it stripped reasoning client-side; or
  4. Document the contract on the Go docs: clients must replay reasoning_content (chat) / reasoning items (responses) for DeepSeek thinking models — today the docs only mandate x-opencode-session, and the "Validated clients" list implies drop-in compatibility that thinking-mode DeepSeek does not currently honor.

Happy to attach redacted failing request bodies (104/111/122-item captures) if useful.

Related

Activity

  1. opencode-agent commented on Oct 22, 2026

    @opencode-agent
    Contributor

    Thanks for the detailed captures and the minimal request.

    This happens inside the hosted Go/Zen gateway, not in the OpenCode app, so we couldn't reproduce it here: our sandbox has no Go account, and the gateway code isn't in this repository. A maintainer with access to the gateway will need to check the request IDs you listed (53529188…, eb8c94c5…, d7fbd6c2…) against the server side. The key question is whether gateway-issued call_ids sometimes fail to find their stored reasoning. A call_id the gateway never issued getting this 400 may be expected, because DeepSeek requires the reasoning to be sent back with earlier tool calls.

    The redacted failing request bodies you offered would help that check, so please attach one if you can.

    Related issues:

  2. sanqiuyef commented on Oct 22, 2026

    @sanqiuyef
    Author

    Answers to the key question, plus the redacted failing request body.

    Provenance check: the failing call_ids are all gateway-issued

    I correlated the failing request d7fbd6c2… (completed 2026-10-22T07:42:29Z, 122 input items, 44 function_call items, zero reasoning items, reasoning_effort: "max") against the captured responses in the same session:

    • 44/44 call_ids in the failing request were issued by the gateway itself in earlier successful responses of the same session.
    • Oldest: call_00_WvcbFtK4nX9QAq4PyI8L6126 — issued 07:06:03Z (first response of the session), replay failed 07:42:29Z (~36 min later).
    • Newest: call_00_jthmk2w452aiqncwqu07fg9l — issued 07:41:06Z by the immediately preceding successful response, replay failed 07:42:29Z (83 seconds later).

    So to your key question: yes — gateway-issued call_ids sometimes fail to find their stored reasoning, even one issued seconds earlier in the same session. That matches the 200/400 flakiness of #51201 better than a simple TTL story (fresh ids miss too, at least intermittently). Failed requests across the day: 53529188… (42 items), eb8c94c5… (104), d7fbd6c2… (122) — identical shape, all with genuine call_00_… ids.

    This also fits #56776 (OpenCode's own client hitting the same 400 on /responses): whether or not the client replays reasoning items, a store miss on any single replayed call_id surfaces the raw DeepSeek 400.

    Redacted failing request body (d7fbd6c2…, /v1/responses)

    All message text, tool arguments and tool outputs are replaced with [redacted N chars]; call_ids and item order are preserved verbatim for server-side correlation. No credentials included (verified by scan).

    redacted request body (122 items)
    {"model": "deepseek-v4.1-flash", "stream": true, "tool_choice": "auto", "reasoning": {"effort": "max"}, "max_output_tokens": 384000, "tools_count": 248, "tools_note": "definitions omitted; names: Agent, AmendWorkflow, AskUserQuestion, Bash, CreateWorkflow, CronCreate, CronDelete, CronList, CronUpdate, Edit, EnterPlanMode, EvalWorkflowSnippet, ExitPlanMode, FillWorkflowHole, GetWorkflowRun, ListModels, ListSavedWorkflows, ListWorkflowRuns, OffPeakCreate, OffPeakList, Read, ReadSessionContext, ReplyToChannel, ResolveWorkflowQuestion, ResumeWorkflowRun, SaveWorkflow, SendMessage, Skill, TaskOutput, TaskStop, TodoRead, TodoWrite, WebFetch, Write, mcp__code-review-graph__apply_refactor_tool, mcp__code-review-graph__build_or_update_graph_tool, mcp__code-review-graph__cross_repo_search_tool, mcp__code-review-graph__detect_changes_tool, mcp__code-review-graph__embed_graph_tool, mcp__code-review-graph__find_large_functions_tool, mcp__code-review-graph__generate_wiki_tool, mcp__code-review-graph__get_affected_flows_tool, mcp__code-review-graph__get_architecture_overview_tool, mcp__code-review-graph__get_bridge_nodes_tool, mcp__code-review-graph__get_community_tool, mcp__code-review-graph__get_docs_section_tool, mcp__code-review-graph__get_flow_tool, mcp__code-review-graph__get_hub_nodes_tool, mcp__code-review-graph__get_impact_radius_tool, mcp__code-review-graph__get_knowledge_gaps_tool, mcp__code-review-graph__get_minimal_context_tool, mcp__code-review-graph__get_review_context_tool, mcp__code-review-graph__get_suggested_questions_tool, mcp__code-review-graph__get_surprising_connections_tool, mcp__code-review-graph__get_wiki_page_tool, mcp__code-review-graph__list_communities_tool, mcp__code-review-graph__list_flows_tool, mcp__code-review-graph__list_graph_stats_tool, mcp__code-review-graph__list_repos_tool, mcp__code-review-graph__query_graph_tool, mcp__code-review-graph__refactor_tool, mcp__code-review-graph__run_postprocess_tool, mcp__code-review-graph__semantic_search_nodes_tool, mcp__code-review-graph__traverse_graph_tool, mcp__codegraph__codegraph_explore, mcp__github-local__get_commit, mcp__github-local__get_file_contents, mcp__github-local__get_label, mcp__github-local__get_latest_release, mcp__github-local__get_me, mcp__github-local__get_release_by_tag, mcp__github-local__get_tag, mcp__github-local__issue_read, mcp__github-local__list_branches, mcp__github-local__list_commits, mcp__github-local__list_issues, mcp__github-local__list_pull_requests, mcp__github-local__list_releases, mcp__github-local__list_repository_collaborators, mcp__github-local__list_tags, mcp__github-local__pull_request_read, mcp__github-local__search_code, mcp__github-local__search_commits, mcp__github-local__search_issues, mcp__github-local__search_pull_requests, mcp__github-local__search_repositories, mcp__github-local__search_users, mcp__global-memory__memory_delete, mcp__global-memory__memory_list, mcp__global-memory__memory_read, mcp__global-memory__memory_search, mcp__global-memory__memory_write, mcp__lancedb-search__add_documents, mcp__lancedb-search__add_single_document, mcp__lancedb-search__ask_knowledge, mcp__lancedb-search__delete_documents, mcp__lancedb-search__get_document, mcp__lancedb-search__get_knowledge_status, mcp__lancedb-search__ingest_images, mcp__lancedb-search__ingest_url, mcp__lancedb-search__list_documents, mcp__lancedb-search__search_images, mcp__lancedb-search__search_knowledge, mcp__lancedb-search__search_similar, mcp__lancedb-search__start_watcher, mcp__lancedb-search__stop_watcher, mcp__lancedb-search__update_document, mcp__mcp-office-writer__batch_edit_office_document, mcp__mcp-office-writer__convert_to_pdf, mcp__mcp-office-writer__create_excel_workbook, mcp__mcp-office-writer__create_pdf_document, mcp__mcp-office-writer__create_powerpoint, mcp__mcp-office-writer__create_word_document, mcp__mcp-office-writer__create_word_from_markdown, mcp__mcp-office-writer__edit_excel_workbook, mcp__mcp-office-writer__edit_open_excel_workbook, mcp__mcp-office-writer__edit_open_powerpoint, mcp__mcp-office-writer__edit_open_word_document, mcp__mcp-office-writer__edit_powerpoint, mcp__mcp-office-writer__edit_word_document, mcp__mcp-office-writer__get_open_office_documents, mcp__mcp-office-writer__inspect_office_document, mcp__mcp-office-writer__merge_office_template, mcp__mcp-office-writer__ppt_add_flowchart_slide, mcp__mcp-office-writer__ppt_analyze_template, mcp__mcp-office-writer__ppt_apply_color_scheme, mcp__mcp-office-writer__ppt_clean_unused_placeholders, mcp__mcp-office-writer__ppt_create_framework_diagram, mcp__mcp-office-writer__ppt_list_color_schemes, mcp__mcp-office-writer__ppt_optimize_slide_layout, mcp__mcp-office-writer__read_excel_workbook, mcp__mcp-office-writer__read_pdf_document, mcp__mcp-office-writer__read_pdf_structured, mcp__mcp-office-writer__read_powerpoint, mcp__mcp-office-writer__read_txt_document, mcp__mcp-office-writer__read_word_document, mcp__mcp-office-writer__recalculate_excel_formulas, mcp__mcp-office-writer__render_document_pages, mcp__mcp-office-writer__validate_word_document, mcp__node_repl__js, mcp__obsidian-cli__append_note, mcp__obsidian-cli__base_query, mcp__obsidian-cli__create_note, mcp__obsidian-cli__daily_append, mcp__obsidian-cli__daily_read, mcp__obsidian-cli__delete_note, mcp__obsidian-cli__eval_js, mcp__obsidian-cli__install_plugin, mcp__obsidian-cli__link_health, mcp__obsidian-cli__list_bases, mcp__obsidian-cli__list_commands, mcp__obsidian-cli__list_files, mcp__obsidian-cli__list_plugins, mcp__obsidian-cli__move_note, mcp__obsidian-cli__note_links, mcp__obsidian-cli__open_note, mcp__obsidian-cli__outline_note, mcp__obsidian-cli__prepend_note, mcp__obsidian-cli__properties, mcp__obsidian-cli__property_get, mcp__obsidian-cli__property_set, mcp__obsidian-cli__read_note, mcp__obsidian-cli__rename_note, mcp__obsidian-cli__run_command, mcp__obsidian-cli__search_context, mcp__obsidian-cli__search_vault, mcp__obsidian-cli__set_plugin, mcp__obsidian-cli__tags, mcp__obsidian-cli__templates, mcp__obsidian-cli__vault_info, mcp__obsidian-cli__web_open, mcp__playwright__browser_click, mcp__playwright__browser_close, mcp__playwright__browser_console_messages, mcp__playwright__browser_drag, mcp__playwright__browser_drop, mcp__playwright__browser_evaluate, mcp__playwright__browser_file_upload, mcp__playwright__browser_fill_form, mcp__playwright__browser_find, mcp__playwright__browser_handle_dialog, mcp__playwright__browser_hover, mcp__playwright__browser_navigate, mcp__playwright__browser_navigate_back, mcp__playwright__browser_network_request, mcp__playwright__browser_network_requests, mcp__playwright__browser_press_key, mcp__playwright__browser_resize, mcp__playwright__browser_run_code_unsafe, mcp__playwright__browser_select_option, mcp__playwright__browser_snapshot, mcp__playwright__browser_tabs, mcp__playwright__browser_take_screenshot, mcp__playwright__browser_type, mcp__playwright__browser_wait_for, mcp__plugin_context7_context7__query-docs, mcp__plugin_context7_context7__resolve-library-id, mcp__plugin_zotero-personal_zotero__add_item, mcp__plugin_zotero-personal_zotero__add_note, mcp__plugin_zotero-personal_zotero__attach_pdf, mcp__plugin_zotero-personal_zotero__authorize_writes, mcp__plugin_zotero-personal_zotero__cite, mcp__plugin_zotero-personal_zotero__clear_highlights, mcp__plugin_zotero-personal_zotero__create_collection, mcp__plugin_zotero-personal_zotero__export_bib, mcp__plugin_zotero-personal_zotero__find_in_pdf, mcp__plugin_zotero-personal_zotero__get_item, mcp__plugin_zotero-personal_zotero__highlight, mcp__plugin_zotero-personal_zotero__list_collections, mcp__plugin_zotero-personal_zotero__open_item, mcp__plugin_zotero-personal_zotero__read_fulltext, mcp__plugin_zotero-personal_zotero__save_highlights, mcp__plugin_zotero-personal_zotero__search_annotations, mcp__plugin_zotero-personal_zotero__search_library, mcp__plugin_zotero-personal_zotero__show_items, mcp__plugin_zotero-personal_zotero__update_item, mcp__python-executor__check_env, mcp__python-executor__clear_session, mcp__python-executor__install_package, mcp__python-executor__list_files, mcp__python-executor__list_packages, mcp__python-executor__list_sessions, mcp__python-executor__read_file, mcp__python-executor__run_python, mcp__python-executor__run_script, mcp__python-executor__sandbox_exec, mcp__python-executor__write_file, mcp__screenshot__capture_desktop, mcp__screenshot__capture_window, mcp__screenshot__list_windows, mcp__web-search-server__batch_web_search, mcp__web-search-server__crates_package_search, mcp__web-search-server__docker_image_search, mcp__web-search-server__download_file, mcp__web-search-server__github_repo_search, mcp__web-search-server__gitlab_repo_search, mcp__web-search-server__huggingface_model_search, mcp__web-search-server__maven_package_search, mcp__web-search-server__npm_package_search, mcp__web-search-server__nuget_package_search, mcp__web-search-server__pypi_package_search, mcp__web-search-server__twitter_search, mcp__web-search-server__web_fetch, mcp__web-search-server__web_search, mcp__web-search-server__web_search_advanced, mcp__web-search-server__web_search_bing, mcp__web-search-server__web_search_google, mcp__web-search-server__web_search_with_content", "input_item_count": 122, "input": [{"type": "message", "role": "system", "content": "[redacted 42 chars]"}, {"type": "message", "role": "system", "content": "[redacted 3098 chars]"}, {"type": "message", "role": "system", "content": "[redacted 7540 chars]"}, {"type": "message", "role": "user", "content": [{"type": "input_text", "text": "[redacted 7930 chars]"}]}, {"type": "message", "role": "user", "content": [{"type": "input_text", "text": "[redacted 8239 chars]"}]}, {"type": "message", "role": "user", "content": [{"type": "input_text", "text": "[redacted 985 chars]"}]}, {"type": "message", "role": "user", "content": [{"type": "input_text", "text": "[redacted 2628 chars]"}]}, {"type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "[redacted 89 chars]"}]}, {"type": "function_call", "call_id": "call_00_WvcbFtK4nX9QAq4PyI8L6126", "name": "Bash", "arguments": "[redacted 172 chars]"}, {"type": "function_call", "call_id": "call_01_ZIYoOWGesC3IEXESVq8o8264", "name": "Bash", "arguments": "[redacted 256 chars]"}, {"type": "function_call_output", "call_id": "call_00_WvcbFtK4nX9QAq4PyI8L6126", "output": "[redacted 3386 chars]"}, {"type": "function_call_output", "call_id": "call_01_ZIYoOWGesC3IEXESVq8o8264", "output": "[redacted 2130 chars]"}, {"type": "function_call", "call_id": "call_00_m8sgxtlfiluy165x16acxdm4", "name": "Read", "arguments": "[redacted 50 chars]"}, {"type": "function_call", "call_id": "call_01_52r4cee1igdjc90fscdf5cbo", "name": "Read", "arguments": "[redacted 58 chars]"}, {"type": "function_call_output", "call_id": "call_00_m8sgxtlfiluy165x16acxdm4", "output": "[redacted 5095 chars]"}, {"type": "function_call_output", "call_id": "call_01_52r4cee1igdjc90fscdf5cbo", "output": "[redacted 7882 chars]"}, {"type": "function_call", "call_id": "call_00_T2O5k2JKfzpN0gBGgvUk4322", "name": "Bash", "arguments": "[redacted 355 chars]"}, {"type": "function_call", "call_id": "call_01_W8KGsCWjyAx7NKTjRwof9608", "name": "Bash", "arguments": "[redacted 397 chars]"}, {"type": "function_call_output", "call_id": "call_00_T2O5k2JKfzpN0gBGgvUk4322", "output": "[redacted 521 chars]"}, {"type": "function_call_output", "call_id": "call_01_W8KGsCWjyAx7NKTjRwof9608", "output": "[redacted 155 chars]"}, {"type": "function_call", "call_id": "call_00_UyKbT8bqjFM3c9gWVX8F4713", "name": "Bash", "arguments": "[redacted 329 chars]"}, {"type": "function_call_output", "call_id": "call_00_UyKbT8bqjFM3c9gWVX8F4713", "output": "[redacted 100 chars]"}, {"type": "function_call", "call_id": "call_00_ET_dLpQLqFEZXVrhDR7j2oa1388", "name": "Bash", "arguments": "[redacted 286 chars]"}, {"type": "function_call_output", "call_id": "call_00_ET_dLpQLqFEZXVrhDR7j2oa1388", "output": "[redacted 89 chars]"}, {"type": "function_call", "call_id": "call_00_ET_GARaBUzXpcrqNpdYRY8m5557", "name": "Bash", "arguments": "[redacted 428 chars]"}, {"type": "function_call_output", "call_id": "call_00_ET_GARaBUzXpcrqNpdYRY8m5557", "output": "[redacted 208 chars]"}, {"type": "function_call", "call_id": "call_00_ut2149r99cm1n9tth12bwu9a", "name": "Bash", "arguments": "[redacted 417 chars]"}, {"type": "function_call_output", "call_id": "call_00_ut2149r99cm1n9tth12bwu9a", "output": "[redacted 215 chars]"}, {"type": "message", "role": "user", "content": [{"type": "input_text", "text": "[redacted 27 chars]"}]}, {"type": "function_call", "call_id": "call_00_9gyxsukd4cjg7akeqqxbi5iu", "name": "Bash", "arguments": "[redacted 641 chars]"}, {"type": "function_call_output", "call_id": "call_00_9gyxsukd4cjg7akeqqxbi5iu", "output": "[redacted 1558 chars]"}, {"type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "[redacted 92 chars]"}]}, {"type": "function_call", "call_id": "call_00_tt4cnj2f1dkihnt0bm62zx01", "name": "Bash", "arguments": "[redacted 628 chars]"}, {"type": "function_call_output", "call_id": "call_00_tt4cnj2f1dkihnt0bm62zx01", "output": "[redacted 4201 chars]"}, {"type": "function_call", "call_id": "call_00_s4ce90lt8hv38jf00td2vrjw", "name": "Bash", "arguments": "[redacted 1118 chars]"}, {"type": "function_call_output", "call_id": "call_00_s4ce90lt8hv38jf00td2vrjw", "output": "[redacted 99 chars]"}, {"type": "message", "role": "user", "content": [{"type": "input_text", "text": "[redacted 421 chars]"}]}, {"type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "[redacted 57 chars]"}]}, {"type": "function_call", "call_id": "call_00_18c5gt4i2zakoylx7ycq90a7", "name": "Bash", "arguments": "[redacted 551 chars]"}, {"type": "function_call_output", "call_id": "call_00_18c5gt4i2zakoylx7ycq90a7", "output": "[redacted 221 chars]"}, {"type": "function_call", "call_id": "call_00_wvqfhmvg9rhfuatwpxvehbxy", "name": "Bash", "arguments": "[redacted 829 chars]"}, {"type": "function_call_output", "call_id": "call_00_wvqfhmvg9rhfuatwpxvehbxy", "output": "[redacted 1487 chars]"}, {"type": "message", "role": "user", "content": [{"type": "input_text", "text": "[redacted 390 chars]"}]}, {"type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "[redacted 92 chars]"}]}, {"type": "function_call", "call_id": "call_00_3b9ebq3ldy1xf8g8wj5bpfkh", "name": "Bash", "arguments": "[redacted 986 chars]"}, {"type": "function_call_output", "call_id": "call_00_3b9ebq3ldy1xf8g8wj5bpfkh", "output": "[redacted 1323 chars]"}, {"type": "function_call", "call_id": "call_00_sijoch5cpbkcfvrk3p8v8miv", "name": "Bash", "arguments": "[redacted 2380 chars]"}, {"type": "function_call_output", "call_id": "call_00_sijoch5cpbkcfvrk3p8v8miv", "output": "[redacted 806 chars]"}, {"type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "[redacted 82 chars]"}]}, {"type": "function_call", "call_id": "call_00_s9n23wrnqs80mqaejkiy0t8d", "name": "Bash", "arguments": "[redacted 2430 chars]"}, {"type": "function_call_output", "call_id": "call_00_s9n23wrnqs80mqaejkiy0t8d", "output": "[redacted 976 chars]"}, {"type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "[redacted 105 chars]"}]}, {"type": "function_call", "call_id": "call_00_ojcv6cbd71stlbe8t6at7q33", "name": "Bash", "arguments": "[redacted 2418 chars]"}, {"type": "function_call_output", "call_id": "call_00_ojcv6cbd71stlbe8t6at7q33", "output": "[redacted 680 chars]"}, {"type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "[redacted 81 chars]"}]}, {"type": "function_call", "call_id": "call_00_rec7zk3vfefzawl6zif8xmth", "name": "Bash", "arguments": "[redacted 358 chars]"}, {"type": "function_call", "call_id": "call_01_f2q8kwx99gs3lo98zwwxw9uq", "name": "Bash", "arguments": "[redacted 198 chars]"}, {"type": "function_call_output", "call_id": "call_00_rec7zk3vfefzawl6zif8xmth", "output": "[redacted 306 chars]"}, {"type": "function_call_output", "call_id": "call_01_f2q8kwx99gs3lo98zwwxw9uq", "output": "[redacted 640 chars]"}, {"type": "function_call", "call_id": "call_00_pqqczw8atvn10am3wu8xt738", "name": "Bash", "arguments": "[redacted 164 chars]"}, {"type": "function_call_output", "call_id": "call_00_pqqczw8atvn10am3wu8xt738", "output": "[redacted 12019 chars]"}, {"type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "[redacted 138 chars]"}]}, {"type": "function_call", "call_id": "call_00_k4fm3wbav2x1mbtec0rfsczy", "name": "Bash", "arguments": "[redacted 524 chars]"}, {"type": "function_call_output", "call_id": "call_00_k4fm3wbav2x1mbtec0rfsczy", "output": "[redacted 185 chars]"}, {"type": "function_call", "call_id": "call_00_vqvcg56k3vflpebjws7g2lle", "name": "Bash", "arguments": "[redacted 661 chars]"}, {"type": "function_call_output", "call_id": "call_00_vqvcg56k3vflpebjws7g2lle", "output": "[redacted 1997 chars]"}, {"type": "message", "role": "user", "content": [{"type": "input_text", "text": "[redacted 421 chars]"}]}, {"type": "function_call", "call_id": "call_00_1z99c1bh6visyb5xlv633m15", "name": "Bash", "arguments": "[redacted 870 chars]"}, {"type": "function_call_output", "call_id": "call_00_1z99c1bh6visyb5xlv633m15", "output": "[redacted 3141 chars]"}, {"type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "[redacted 97 chars]"}]}, {"type": "function_call", "call_id": "call_00_n1oxqeqpw7zofy781abz3cde", "name": "Bash", "arguments": "[redacted 163 chars]"}, {"type": "function_call", "call_id": "call_01_q3mm93lgzbqp4235w6dc9d7e", "name": "Bash", "arguments": "[redacted 604 chars]"}, {"type": "function_call_output", "call_id": "call_00_n1oxqeqpw7zofy781abz3cde", "output": "[redacted 613 chars]"}, {"type": "function_call_output", "call_id": "call_01_q3mm93lgzbqp4235w6dc9d7e", "output": "[redacted 3055 chars]"}, {"type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "[redacted 117 chars]"}]}, {"type": "function_call", "call_id": "call_00_m6v9d2zexmc9y3n3mukvmgi6", "name": "Bash", "arguments": "[redacted 2481 chars]"}, {"type": "function_call_output", "call_id": "call_00_m6v9d2zexmc9y3n3mukvmgi6", "output": "[redacted 1377 chars]"}, {"type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "[redacted 226 chars]"}]}, {"type": "function_call", "call_id": "call_00_0dlcnvpqmp2agwr99f6a8ikf", "name": "Bash", "arguments": "[redacted 560 chars]"}, {"type": "function_call_output", "call_id": "call_00_0dlcnvpqmp2agwr99f6a8ikf", "output": "[redacted 207 chars]"}, {"type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "[redacted 58 chars]"}]}, {"type": "function_call", "call_id": "call_00_inqesqwosy8n73gt29svnix3", "name": "Bash", "arguments": "[redacted 2457 chars]"}, {"type": "function_call_output", "call_id": "call_00_inqesqwosy8n73gt29svnix3", "output": "[redacted 337 chars]"}, {"type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "[redacted 25 chars]"}]}, {"type": "function_call", "call_id": "call_00_3x0n5o2p3nr1wn7snqscm3jz", "name": "Bash", "arguments": "[redacted 389 chars]"}, {"type": "function_call_output", "call_id": "call_00_3x0n5o2p3nr1wn7snqscm3jz", "output": "[redacted 71 chars]"}, {"type": "function_call", "call_id": "call_00_zye9igomnw5gwjznnuzuv6gs", "name": "Bash", "arguments": "[redacted 479 chars]"}, {"type": "function_call", "call_id": "call_01_wl6023aeuue7nec32g3jc2yv", "name": "Bash", "arguments": "[redacted 273 chars]"}, {"type": "function_call_output", "call_id": "call_00_zye9igomnw5gwjznnuzuv6gs", "output": "[redacted 166 chars]"}, {"type": "function_call_output", "call_id": "call_01_wl6023aeuue7nec32g3jc2yv", "output": "[redacted 380 chars]"}, {"type": "message", "role": "user", "content": [{"type": "input_text", "text": "[redacted 999 chars]"}]}, {"type": "function_call", "call_id": "call_00_onqguj1dwl1rpb0qbyd2yo1v", "name": "Read", "arguments": "[redacted 157 chars]"}, {"type": "function_call_output", "call_id": "call_00_onqguj1dwl1rpb0qbyd2yo1v", "output": "[redacted 2134 chars]"}, {"type": "function_call", "call_id": "call_00_h3ehqbfuuxnxb3o4cs9ybiqb", "name": "Bash", "arguments": "[redacted 2261 chars]"}, {"type": "function_call_output", "call_id": "call_00_h3ehqbfuuxnxb3o4cs9ybiqb", "output": "[redacted 809 chars]"}, {"type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "[redacted 88 chars]"}]}, {"type": "function_call", "call_id": "call_00_gcnwt5nthax19wrqqaahuqwp", "name": "Bash", "arguments": "[redacted 2491 chars]"}, {"type": "function_call_output", "call_id": "call_00_gcnwt5nthax19wrqqaahuqwp", "output": "[redacted 423 chars]"}, {"type": "message", "role": "user", "content": [{"type": "input_text", "text": "[redacted 421 chars]"}]}, {"type": "function_call", "call_id": "call_00_ET_iSDHOxFaD4gylbw7do5Y1822", "name": "Bash", "arguments": "[redacted 2504 chars]"}, {"type": "function_call_output", "call_id": "call_00_ET_iSDHOxFaD4gylbw7do5Y1822", "output": "[redacted 549 chars]"}, {"type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "[redacted 206 chars]"}]}, {"type": "function_call", "call_id": "call_00_sag4oc0adppxgffkpfatcrts", "name": "Bash", "arguments": "[redacted 630 chars]"}, {"type": "function_call_output", "call_id": "call_00_sag4oc0adppxgffkpfatcrts", "output": "[redacted 6763 chars]"}, {"type": "message", "role": "user", "content": [{"type": "input_text", "text": "[redacted 387 chars]"}]}, {"type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "[redacted 109 chars]"}]}, {"type": "function_call", "call_id": "call_00_4k8331hsd5mgehkbjm7jr5t2", "name": "Bash", "arguments": "[redacted 2098 chars]"}, {"type": "function_call_output", "call_id": "call_00_4k8331hsd5mgehkbjm7jr5t2", "output": "[redacted 547 chars]"}, {"type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "[redacted 107 chars]"}]}, {"type": "function_call", "call_id": "call_00_0uelcckd873qrco6md9i0lbg", "name": "Bash", "arguments": "[redacted 1108 chars]"}, {"type": "function_call_output", "call_id": "call_00_0uelcckd873qrco6md9i0lbg", "output": "[redacted 299 chars]"}, {"type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "[redacted 99 chars]"}]}, {"type": "function_call", "call_id": "call_00_ub3ap1thsgaxnfo8u00tfnxt", "name": "Bash", "arguments": "[redacted 471 chars]"}, {"type": "function_call_output", "call_id": "call_00_ub3ap1thsgaxnfo8u00tfnxt", "output": "[redacted 8227 chars]"}, {"type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "[redacted 72 chars]"}]}, {"type": "function_call", "call_id": "call_00_4l787aw74hdxjdew0ch5bfqc", "name": "Bash", "arguments": "[redacted 683 chars]"}, {"type": "function_call_output", "call_id": "call_00_4l787aw74hdxjdew0ch5bfqc", "output": "[redacted 1353 chars]"}, {"type": "function_call", "call_id": "call_00_yn9twkwidd51sciqfts3dyym", "name": "Bash", "arguments": "[redacted 716 chars]"}, {"type": "function_call_output", "call_id": "call_00_yn9twkwidd51sciqfts3dyym", "output": "[redacted 1381 chars]"}, {"type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "[redacted 53 chars]"}]}, {"type": "function_call", "call_id": "call_00_jthmk2w452aiqncwqu07fg9l", "name": "Bash", "arguments": "[redacted 2950 chars]"}, {"type": "function_call_output", "call_id": "call_00_jthmk2w452aiqncwqu07fg9l", "output": "[redacted 421 chars]"}]}

    The two other failing requests (53529188…, eb8c94c5…) have the same shape with 42 and 104 items; happy to attach them too if useful.

  3. VictorHMH18713 commented on Oct 27, 2026

    @VictorHMH18713

    Same failure family, but reached through the Anthropic-native route (POST /zen/go/v1/messages), from Claude Code — which the Go docs list as a validated client. Two extra data points: the client never replays thinking either, and on streaming requests the gateway drops the upstream body entirely.

    Environment

    item value
    Client Claude Code 2.1.293 (claude-cli/2.1.293), ANTHROPIC_BASE_URL=https://opencode.ai/zen/go
    Route Anthropic Messages API (/zen/go/v1/messages), stream: true
    Model deepseek-v4.1-flash (effort high)
    Session header Claude Code's native X-Claude-Code-Session-Id (recognized per the Go docs, no x-opencode-session needed)
    Observed 2026-10-27 07:24–07:44Z, 07:53Z, 08:15Z (all UTC)

    Symptom

    API Error: 400 status code (no body)
    

    Replaying the exact same conversation non-streaming returns the upstream error, so it is the same root cause as this issue, just surfacing on the Anthropic route:

    {"type":"error","error":{"type":"invalid_request_error","message":"Upstream request failed: [invalid_request_error] The `content[].thinking` in the thinking mode must be passed back to the API. (request_id: 65871f21-0908-4a0f-bc02-89f7c5fb6d1f) (request id: 202610270826085305488478268d9d6RBCXETWj)"}}

    Same body with "stream": true → HTTP 400 with a 0-byte body. That is why the client shows (no body) and why the failure is opaque to the user (related masking issue: #51530).

    Evidence that this is the same call_id store-miss

    1. Every tool call in the failing request was issued by the gateway. In the failing subagent, 15/15 tool_use ids are call_00_… ids returned by earlier gateway responses in the same session:

    call_00_isgefp3osjgl0fcpkd022y14  …  call_00_gr657gve2ujk5pm4nibxxs1k
    

    So this is not a client-invented id; the reasoning lookup should have hit.

    2. The client never replays thinking, and the gateway usually compensates. Claude Code's request history contains assistant tool_use turns with no thinking block at all (100% of tool-call turns in its transcripts). Most of these requests return 200 — reasoning is being backfilled server-side, same conclusion as your report.

    3. Identical bytes flap between 200 and 400 within minutes. A 67 KB reconstructed body (Anthropic format, stream: true, 52 messages) sent repeatedly:

    08:26:08Z  400, 400, 200, 400   (4 attempts)
    08:30Z     200 × 10             (same bytes, no changes)
    08:36Z     200 × 8
    

    This matches the store-miss/TTL pattern described here, and also matches #51201 ("identical bytes replay 200/400/200").

    4. Blast radius. On this machine it killed 8 of 25 dynamic-workflow subagents (32%) inside one 20-minute window, all with the same 400; outside that window, none. Claude Code does not retry it: its retry predicate is 408 / 409 / 429 / 5xx / x-should-retry: true, so a single 400 terminates the subagent and the orchestration script gets null instead of the result. Because every subagent shares the parent X-Claude-Code-Session-Id, one store-miss keeps failing on subsequent turns of the same session (we saw 4 consecutive failures over 11 s on one conversation).

    Asks

    1. On the gateway side, could 65871f21-0908-4a0f-bc02-89f7c5fb6d1f / 202610270826085305488478268d9d6RBCXETWj be checked against the reasoning store? Specifically whether the Anthropic route keys the store the same way (call_id from tool_use.id) and whether those entries were evicted (TTL, session-affinity change between calls).
    2. Return a JSON error body on streaming requests too — a 0-byte 400 is indistinguishable from a bad request generated client-side, and it hides exactly the information needed to report this.
    3. If the store miss is expected to happen, an internal single retry (or re-injecting empty reasoning with the correct shape) on the gateway would turn a hard subagent failure into a slow turn.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    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