[BUG] Multi-turn HTTP 400 on openrouter-routed DeepSeek V4 Flash; same env works with MiniMax-M3

Open 💬 2 comments Opened Jun 17, 2026 by StefanIsMe

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?

Multi-turn HTTP 400 when Claude Code is routed through OpenRouter to DeepSeek V4 Flash. First turn succeeds, every subsequent turn returns "API Error: 400 Provider returned error" and the session is unrecoverable. Same env, same Claude Code version, works fine with MiniMax-M3 (TokenRouter, 220+ multi-turn turns, 0 errors).

What Should Happen?

Multi-turn conversations should complete without errors when Claude Code is routed through OpenRouter to any supported model. The thinking block Claude Code generates on turn N should be preserved or translated on turn N+1 in a way the routed model accepts. Models that require thinking passback (per their own API contract) should not break Claude Code's session on the second turn.

Error Messages/Logs

API Error: 400 Provider returned error

    From the session JSONL (turn 1 then turn 2 of the same conversation):

    Turn 1 (success):
      model: deepseek/deepseek-v4-flash-20260423
      provider: DeepSeek
      stop_reason: tool_use
      input_tokens: 24881
      output_tokens: 272
      content[0].type: thinking  length: 823  signature: <empty>
      content[1].type: tool_use  name: Skill

    Turn 2 (400):
      model: <synthetic>
      provider: <none>
      stop_reason: stop_sequence
      isApiErrorMessage: true
      apiErrorStatus: 400
      error: unknown
      input_tokens: 0
      output_tokens: 0
      content[0].text: "API Error: 400 Provider returned error"

    The thinking block on turn 1 has an empty signature field. The next request fails before any tokenization, suggesting the request body fails validation upstream.

Steps to Reproduce

  1. Install Claude Code: npm install -g @anthropic-ai/claude-code
  2. Configure ~/.claude/settings.json with:

"env": {
"ANTHROPIC_BASE_URL": "https://openrouter.ai/api",
"ANTHROPIC_AUTH_TOKEN": "<openrouter-key>",
"ANTHROPIC_MODEL": "openrouter/auto"
}

  1. Launch claude interactively from a terminal.
  2. Send a normal coding question, e.g. "read README.md and summarize".
  3. The first assistant turn succeeds (tool use, thinking block, etc.).
  4. Send any follow-up turn, e.g. "now add a section on installation".
  5. Response: "API Error: 400 Provider returned error".
  6. From this point every subsequent turn in the same session also returns 400.
  7. The session must be closed and a new claude process started to recover.

Pinning ANTHROPIC_MODEL to a specific non-Claude model on OpenRouter (e.g. deepseek/deepseek-v4-flash-20260423) reproduces the same 400. The auth env var can be set to either ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY; the failure is not auth-related.

Claude Model

openrouter/auto (resolves to deepseek/deepseek-v4-flash-20260423 via OpenRouter NotDiamond routing)

Is this a regression?

It's not a version regression.

Last Working Version

Not a Claude Code version regression — same version 2.1.178 works fine with model=MiniMax-M3 (TokenRouter, three sessions, 370+ multi-turn assistant turns, 0 errors). The 400 reproduces on 2.1.178 AND 2.1.179 when the routed model is DeepSeek V4 Flash. The change that introduced the failure was the model/provider choice, not the Claude Code version.

Claude Code Version

2.1.179 (Claude Code)

Platform

OpenRouter (https://openrouter.ai/api) — Anthropic Skin translation layer

Operating System

Fedora Linux 44 (Workstation Edition), kernel 7.0.8-200.fc44.x86_64

Terminal/Shell

Ghostty (xterm-ghostty), bash 5.3.9, Wayland, GNOME

Additional Information

  • The thinking block on turn 1 has an empty/missing signature field in the JSONL. This matches the failure mode described in issue #62963 (2.1.152 thinking-by-default regression) but reproduces on the current 2.1.179 build.
  • DeepSeek's API contract (api-docs.deepseek.com/guides/thinking_mode) requires the thinking content to be passed back in the assistant's prior message on subsequent requests. Claude Code's serializer does not preserve it correctly when routing through OpenRouter to DeepSeek, causing 400.
  • Related: musistudio/claude-code-router#1378 (DeepSeek V4 Pro thinking-mode + tool calls fails identically on the same env, with a working translation-proxy workaround).
  • A translation proxy that injects reasoning_content on the round-trip (e.g. laichunpongben/deepseek-reasoning-proxy) is the only working workaround I have found. Pinning to a non-thinking-passback model also works.
  • I tested with only ANTHROPIC_AUTH_TOKEN set (no ANTHROPIC_API_KEY) and with both set — the 400 reproduces either way. The auth conflict warning in the boot banner is a separate issue and is not the cause of the 400.
  • Cost: I have not been charged for the failing requests. The 400 is rejected at the provider edge before any model inference.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗