Claude Code v2.1.167: Agent() spawn fails with "400 thinking options type cannot be disabled when reasoning_effort is set" on DeepSeek Anthropic-compatible endpoint
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Environment
- Claude Code: v2.1.167 (npm global install)
- OS: Windows 11 x64
- API Endpoint:
ANTHROPIC_BASE_URL=https://api.deepseek.com/anthropic - Main model:
ANTHROPIC_MODEL=deepseek-v4-pro(works fine for main conversation) - Sub-agent models:
ANTHROPIC_DEFAULT_SONNET_MODEL=deepseek-v4-flash,ANTHROPIC_DEFAULT_HAIKU_MODEL=deepseek-v4-flash(set at Windows User env level)
Steps to Reproduce
- Configure Claude Code to use DeepSeek's Anthropic-compatible endpoint
ANTHROPIC_BASE_URL=https://api.deepseek.com/anthropicANTHROPIC_MODEL=deepseek-v4-pro- Run any Agent spawn:
Agent({ model: "sonnet", subagent_type: "general-purpose", ... }) - Observe error:
API Error: 400 thinking options type cannot be disabled when reasoning_effort is set
Same error occurs with:
- WebSearch tool
- WebFetch tool
- All three Agent model tiers (sonnet/haiku/opus)
What Works
- Main conversation on
deepseek-v4-pro→ ✅ perfect - All non-subprocess tools (Read, Write, Edit, Bash, Grep, Glob, etc.) → ✅
What We Tested (Direct API Verification)
We ran 11 direct curl tests to DeepSeek's /anthropic/v1/messages endpoint with thinking: {type: "disabled"} combined with various parameters. All returned 200:
| # | model | extra params | Result |
|---|-------|-------------|--------|
| 1 | v4-pro | — | ✅ |
| 2 | v4-pro | tools:[...] | ✅ |
| 3 | v4-pro | tools + system | ✅ |
| 4 | v4-pro | tools + system + tool_choice:{type:"auto"} | ✅ |
| 5 | v4-pro | reasoning_effort:"high" | ✅ |
| 6 | v4-pro | budget_tokens:0 | ✅ |
| 7 | v4-flash | — | ✅ |
| 8 | v4-flash | tools + system | ✅ |
| 9 | claude-sonnet-4-20250514 | Anthropic model ID (mapped to v4-flash by DeepSeek) | ✅ |
This demonstrates that DeepSeek's Anthropic-compatible endpoint fully supports thinking: disabled — the 400 error is specific to Claude Code's Agent subprocess API request path.
Environment Variable Investigation
We tried setting ANTHROPIC_DEFAULT_SONNET/HAIKU_MODEL=deepseek-v4-flash via three different paths:
- settings.json
envblock - Windows User-level registry (permanent)
- Post-restart process inheritance
All three correctly set the env vars (confirmed via echo in subprocesses), but Agent spawn still fails with the same 400 — suggesting the Agent subprocess mechanism bypasses these env vars entirely.
Hypothesis
Claude Code's Agent subprocess API request construction differs from the main conversation path. The subprocess may:
- Send a parameter or header combination not covered by our direct API tests
- Use a different HTTP endpoint path
- Use a different SDK code path that triggers the error
Workaround
Direct execution by Team Lead (no Agent spawn). Quality is unaffected — verified with Critic review scoring 9.0/10 on directly-executed page reviews.
Additional Context
This bug was discovered during systematic /lint --system auditing of a production Obsidian knowledge base (~41K files). The Agent system (Writer/Critic/Researcher with state files, memory, and inter-agent cache channels) was fully deployed but had zero usage over 5 days because every spawn attempt failed silently. The knowledge base has comprehensive self-monitoring protocols that detected the anomaly.
What Should Happen?
Environment
- Claude Code: v2.1.167 (npm global install)
- OS: Windows 11 x64
- API Endpoint:
ANTHROPIC_BASE_URL=https://api.deepseek.com/anthropic - Main model:
ANTHROPIC_MODEL=deepseek-v4-pro(works fine for main conversation) - Sub-agent models:
ANTHROPIC_DEFAULT_SONNET_MODEL=deepseek-v4-flash,ANTHROPIC_DEFAULT_HAIKU_MODEL=deepseek-v4-flash(set at Windows User env level)
Steps to Reproduce
- Configure Claude Code to use DeepSeek's Anthropic-compatible endpoint
ANTHROPIC_BASE_URL=https://api.deepseek.com/anthropicANTHROPIC_MODEL=deepseek-v4-pro- Run any Agent spawn:
Agent({ model: "sonnet", subagent_type: "general-purpose", ... }) - Observe error:
API Error: 400 thinking options type cannot be disabled when reasoning_effort is set
Same error occurs with:
- WebSearch tool
- WebFetch tool
- All three Agent model tiers (sonnet/haiku/opus)
What Works
- Main conversation on
deepseek-v4-pro→ ✅ perfect - All non-subprocess tools (Read, Write, Edit, Bash, Grep, Glob, etc.) → ✅
What We Tested (Direct API Verification)
We ran 11 direct curl tests to DeepSeek's /anthropic/v1/messages endpoint with thinking: {type: "disabled"} combined with various parameters. All returned 200:
| # | model | extra params | Result |
|---|-------|-------------|--------|
| 1 | v4-pro | — | ✅ |
| 2 | v4-pro | tools:[...] | ✅ |
| 3 | v4-pro | tools + system | ✅ |
| 4 | v4-pro | tools + system + tool_choice:{type:"auto"} | ✅ |
| 5 | v4-pro | reasoning_effort:"high" | ✅ |
| 6 | v4-pro | budget_tokens:0 | ✅ |
| 7 | v4-flash | — | ✅ |
| 8 | v4-flash | tools + system | ✅ |
| 9 | claude-sonnet-4-20250514 | Anthropic model ID (mapped to v4-flash by DeepSeek) | ✅ |
This demonstrates that DeepSeek's Anthropic-compatible endpoint fully supports thinking: disabled — the 400 error is specific to Claude Code's Agent subprocess API request path.
Environment Variable Investigation
We tried setting ANTHROPIC_DEFAULT_SONNET/HAIKU_MODEL=deepseek-v4-flash via three different paths:
- settings.json
envblock - Windows User-level registry (permanent)
- Post-restart process inheritance
All three correctly set the env vars (confirmed via echo in subprocesses), but Agent spawn still fails with the same 400 — suggesting the Agent subprocess mechanism bypasses these env vars entirely.
Hypothesis
Claude Code's Agent subprocess API request construction differs from the main conversation path. The subprocess may:
- Send a parameter or header combination not covered by our direct API tests
- Use a different HTTP endpoint path
- Use a different SDK code path that triggers the error
Workaround
Direct execution by Team Lead (no Agent spawn). Quality is unaffected — verified with Critic review scoring 9.0/10 on directly-executed page reviews.
Additional Context
This bug was discovered during systematic /lint --system auditing of a production Obsidian knowledge base (~41K files). The Agent system (Writer/Critic/Researcher with state files, memory, and inter-agent cache channels) was fully deployed but had zero usage over 5 days because every spawn attempt failed silently. The knowledge base has comprehensive self-monitoring protocols that detected the anomaly.
Error Messages/Logs
Steps to Reproduce
Environment
- Claude Code: v2.1.167 (npm global install)
- OS: Windows 11 x64
- API Endpoint:
ANTHROPIC_BASE_URL=https://api.deepseek.com/anthropic - Main model:
ANTHROPIC_MODEL=deepseek-v4-pro(works fine for main conversation) - Sub-agent models:
ANTHROPIC_DEFAULT_SONNET_MODEL=deepseek-v4-flash,ANTHROPIC_DEFAULT_HAIKU_MODEL=deepseek-v4-flash(set at Windows User env level)
Steps to Reproduce
- Configure Claude Code to use DeepSeek's Anthropic-compatible endpoint
ANTHROPIC_BASE_URL=https://api.deepseek.com/anthropicANTHROPIC_MODEL=deepseek-v4-pro- Run any Agent spawn:
Agent({ model: "sonnet", subagent_type: "general-purpose", ... }) - Observe error:
API Error: 400 thinking options type cannot be disabled when reasoning_effort is set
Same error occurs with:
- WebSearch tool
- WebFetch tool
- All three Agent model tiers (sonnet/haiku/opus)
What Works
- Main conversation on
deepseek-v4-pro→ ✅ perfect - All non-subprocess tools (Read, Write, Edit, Bash, Grep, Glob, etc.) → ✅
What We Tested (Direct API Verification)
We ran 11 direct curl tests to DeepSeek's /anthropic/v1/messages endpoint with thinking: {type: "disabled"} combined with various parameters. All returned 200:
| # | model | extra params | Result |
|---|-------|-------------|--------|
| 1 | v4-pro | — | ✅ |
| 2 | v4-pro | tools:[...] | ✅ |
| 3 | v4-pro | tools + system | ✅ |
| 4 | v4-pro | tools + system + tool_choice:{type:"auto"} | ✅ |
| 5 | v4-pro | reasoning_effort:"high" | ✅ |
| 6 | v4-pro | budget_tokens:0 | ✅ |
| 7 | v4-flash | — | ✅ |
| 8 | v4-flash | tools + system | ✅ |
| 9 | claude-sonnet-4-20250514 | Anthropic model ID (mapped to v4-flash by DeepSeek) | ✅ |
This demonstrates that DeepSeek's Anthropic-compatible endpoint fully supports thinking: disabled — the 400 error is specific to Claude Code's Agent subprocess API request path.
Environment Variable Investigation
We tried setting ANTHROPIC_DEFAULT_SONNET/HAIKU_MODEL=deepseek-v4-flash via three different paths:
- settings.json
envblock - Windows User-level registry (permanent)
- Post-restart process inheritance
All three correctly set the env vars (confirmed via echo in subprocesses), but Agent spawn still fails with the same 400 — suggesting the Agent subprocess mechanism bypasses these env vars entirely.
Hypothesis
Claude Code's Agent subprocess API request construction differs from the main conversation path. The subprocess may:
- Send a parameter or header combination not covered by our direct API tests
- Use a different HTTP endpoint path
- Use a different SDK code path that triggers the error
Workaround
Direct execution by Team Lead (no Agent spawn). Quality is unaffected — verified with Critic review scoring 9.0/10 on directly-executed page reviews.
Additional Context
This bug was discovered during systematic /lint --system auditing of a production Obsidian knowledge base (~41K files). The Agent system (Writer/Critic/Researcher with state files, memory, and inter-agent cache channels) was fully deployed but had zero usage over 5 days because every spawn attempt failed silently. The knowledge base has comprehensive self-monitoring protocols that detected the anomaly.
Claude Model
Other
Is this a regression?
Yes, this worked in a previous version
Last Working Version
_No response_
Claude Code Version
2.1.167 (Claude Code)
Platform
Other
Operating System
Windows
Terminal/Shell
PowerShell
Additional Information
_No response_
14 Comments
Your test matrix is excellent and it actually contains the answer — there's one cell missing that I think is the whole bug.
Look at what you proved vs. what the subprocess does:
thinking:{type:"disabled"}+reasoning_effort:"high"→ 200 (your test #5). So v4-pro tolerates the combo.thinking:{type:"disabled"}alone → 200 (#7, #8). So v4-flash toleratesthinking:disabledwhen reasoning_effort is absent.thinking:{type:"disabled"}+reasoning_efforttogether → you never tested this cell.That missing cell is exactly what the Agent path sends. Your sub-agents are mapped to
deepseek-v4-flash(ANTHROPIC_DEFAULT_SONNET_MODEL/HAIKU_MODEL), and Claude Code's sub-agent/tool request path sendsreasoning_effortandthinking:{type:"disabled"}in the same request (sub-agents disable extended thinking by default to save tokens, while the tier still carries a reasoning_effort). The error string — "thinking options type cannot be disabled when reasoning_effort is set" — is DeepSeek rejecting that combination, and it appears to be model-specific: v4-pro accepts it (#5), v4-flash evidently does not. The main conversation works because it runs on v4-pro.Two things to try:
1. Confirm it with the one curl you didn't run (this should reproduce the 400 directly, with no Claude Code involved):
If that returns the same 400, the bug is the flash model rejecting the pair, not the Agent plumbing per se — which also explains why none of your env-var attempts helped (they set the model correctly; the model is the thing that rejects the combo).
2. Workaround that should unblock you today: point the sub-agent tiers at the model you already proved accepts the combo —
deepseek-v4-proinstead ofv4-flash:You lose the flash cost saving on sub-agents, but Agent/WebSearch/WebFetch spawns should start succeeding immediately since v4-pro tolerates
thinking:disabled+reasoning_effort(your #5).If you want to keep flash for sub-agents, the real fix is on the Claude Code side — it should not send
reasoning_effortalongsidethinking:{type:"disabled"}for the sub-agent path (or should omit one when targeting a model that rejects the pair). Worth noting that in the issue as the upstream ask, with the single curl above as the minimal repro — it's much tighter than the Agent-spawn repro and doesn't depend on your Obsidian setup at all.Replying to @yurukusa's workaround suggestion:
The workaround does not work. We set every subagent tier to
deepseek-v4-pro[1m](not flash), removedCLAUDE_CODE_EFFORT_LEVEL, verified the env — and Agent spawn still returns the same 400:Agent spawn still fails:
API Error: 400 thinking options type cannot be disabled when reasoning_effort is setThe missing curl cell also doesn't reproduce the theory
We ran both of the missing-cell tests directly against DeepSeek:
| model | thinking:disabled + reasoning_effort:"high" | Result |
|-------|---------------------------------------------|--------|
|
deepseek-v4-pro[1m]| yes | ✅ 200 ||
deepseek-v4-flash| yes | ✅ 200 |Both accept the combo. This suggests Claude Code's Agent subprocess request path sends something materially different from what a straightforward curl captures — a different parameter, header, or endpoint path. The bug is in the harness, not in model selection.
Environment: Linux WSL2, Claude Code v2.1.168.
I also encountered the same problem. All the solutions were ineffective. So I decided to roll back the version.
EDIT2: tweaked the code
https://github.com/seedlord/deepseek-proxy
<img width="1317" height="414" alt="Image" src="https://github.com/user-attachments/assets/1a99c506-ae62-4d70-b92a-50db27ca1f21" />
<details>
DeepSeek Cache-Safe Proxy
A zero-dependency Node.js HTTP proxy that sits between the Claude Code VS Code extension and the DeepSeek API. It inspects, displays, and logs API traffic in a terminal TUI while forwarding requests — with optional subagent thinking overrides.
!Platform
!Node
!Dependencies
<br>🌐 中文文档
!Screenshot
Features
thinkingandoutput_configinto subagent requests so they inherit the main session's reasoning budget. Toggle on/off with a single keypress.lib/*modules without restarting the process. Log buffer and terminal state are preserved.j/k,g/G,PgUp/PgDn). Header stays live.Quick Start
Then configure Claude Code to use
http://localhost:4000as its API endpoint.Environment Variables
| Variable | Default | Description |
|---|---|---|
|
PROXY_PORT|4000| Listening port ||
DEEPSEEK_HOST|api.deepseek.com| Upstream API host ||
PROXY_LOG_FILE|./proxy-metrics.csv| CSV output path ||
PROXY_MAX_BODY|52428800(50 MB) | Max request body size ||
PROXY_REQ_TIMEOUT|120000(120s) | Outbound request timeout ||
PROXY_SRV_TIMEOUT|130000(130s) | Inbound/server timeout |Architecture
Request flow: Client → HTTP server → body read with size cap → JSON parse → payload inspection → session detection (via auth header fingerprint) → subagent thinking override (if applicable) → forward to DeepSeek via HTTPS keep-alive → streaming response → metrics extraction from tail buffer → TUI log + separated MAIN/SUB cache stats + CSV append.
HTTP Endpoints
| Method | Path | Description |
|---|---|---|
|
POST|/*| Forward to DeepSeek (JSON body required) ||
GET|/toggle| Toggle subagent thinking override ||
GET|/toggle-log| Toggle CSV file logging ||
GET|/toggle-debug| Toggle debug logging ||
GET|/health| Health check (uptime, request count, toggle states) ||
GET|/status| Brief status (toggles + request count) ||
GET|/metrics| Download CSV log (503 if logging disabled) |Keyboard Controls
| Key | Action |
|---|---|
|
t| Toggle subagent thinking override ||
l| Toggle CSV file logging ||
d| Toggle debug logging ||
r| Redraw screen ||
R| Reset MAIN cache stats (no reload) ||
p| Enter/exit pager mode (scrollback) ||
s| Print stats line to log ||
h| Reset MAIN stats + hot reload alllib/*modules ||
q| Quit |Pager Mode Keys
| Key | Action |
|---|---|
|
j/↓| Scroll down one line ||
k/↑| Scroll up one line ||
PageUp| Scroll up 10 lines ||
PageDown| Scroll down 10 lines ||
g| Jump to top of log buffer ||
G| Jump to bottom (resume follow) ||
p/q/Esc| Exit pager, return to follow mode |CSV Output
Each request appends one row to the CSV log. Columns:
timestamp, role, agentId, model, thinkingType, thinkingBudget, maxTokens, msgCount, systemLen, lastTools, lastUserHint, callTools, missTokens, cacheHitTokens, cacheHitPct, outputTokens, reasoningTokensMAINorSUB(subagent)Requirements
http,https,fs,readlinebuilt-insLicense
MIT
</details>
我也碰到了同样的问题
测试有效
the proxy solved my problem. But I would love that anthropic launches an official solution for the problem.
Works perfectly! Thank you @seedlord for the proxy solution. Confirmed working on Claude Code v2.1.169 + DeepSeek v4-pro. WebSearch, WebFetch, and Agent spawn all functional again after setting up this proxy. Saved us from having to downgrade. 🙏
For anyone else finding this: the key is to run the proxy with
nohupso it survives terminal sessions, and don't forget to addANTHROPIC_BASE_URLto the env section of settings.json (not just the shell environment).wow,thinks!!!!!!!!!!
最好的方法,退回165,并且禁用自动更新
Thinks!!!!!!!
Using LiteLLM's proxy hooks to fix the DeepSeek thinking parameter conflict
Thanks to seedlord (@seedlord) for the original idea of using a proxy to strip conflicting parameters before forwarding requests to DeepSeek.
This solution applies to anyone using an LLM gateway (LiteLLM, etc.) to proxy API calls between Claude Code and a third-party LLM provider that strictly validates Anthropic-compatible request schemas.
If you're encountering this 400 error when using Claude Code (v2.1.166+) with DeepSeek API through LiteLLM:
Root Cause
Claude Code v2.1.166+ intentionally sets
"thinking": {"type": "disabled"}for subagent tasks to save costs, but fails to strip global reasoning parameters (reasoning_effort,output_config) from the payload. The official Anthropic API tolerates these contradictory fields, but DeepSeek's API strictly validates and rejects them.Solution
Uses LiteLLM's built-in
async_pre_call_hookcallback to strip conflicting parameters before the request is forwarded to DeepSeek. No additional proxy process needed — everything runs inside LiteLLM.Implementation
Create
custom_handler.pyConfigure LiteLLM to use the handler
Register the callback in your LiteLLM
config.yaml:How It Works
References
async_pre_call_hookNotes
thinking(e.g.{"type": "adaptive"}) are left untouched.call_typefor Anthropic-format requests isanthropic_messages(notpass_through_endpoint).The
400 thinking options type cannoterror happens when the CLI sends athinkingparam with an invalid type (e.g., string instead of object, or vice versa). This is a client-side serialization bug — thethinkingfield should be"thinking": {"type": "enabled", "budget_tokens": N}not"thinking": "enabled"or similar.If you want to see exactly what the CLI is sending before it hits the API, run it behind a local proxy. The proxy will log the raw JSON body so you can confirm whether the
thinkingfield is malformed. That narrows it down to "is this the CLI or is this my config" instantly.If valid object error pass through . Then user should look at usage and the tokens it burn to pass through the description of the prompt and the prompt validation through out the session. Alternative to guided onto on one-one transcription . The idea need to be legitimate and purely recreatable over screen space . The texts that required , The design shape , Curve integrities . The animations of the page that need to follow . The retracted sections of div. Incase if cached . The temporal access via trivia . A small change to deduce complete idea format . If the type was invalid . try changing description of how to curl in it same space dependencies . Ask more questions regarding tkintering , The polishing of substrates to actualize visual description . [Check or whether [The generated matched the outsourced idea]] . If route is able to concat it onto host server and server worker space immediately. . Then it could be easily handled over.
clean tucks of pre-responsive model , Generations proliferated but leaking outwards . Temperature diffused , Matches currentnetdc. If tucks [Ts] are valid . Provide a j-prod . S-son : <Lecture distributed Logics> to counter-rate , The responsive mechanism and loading session via alternate host.