Skip to content

[Bug] preserveReasoningContentModels still emits bare tool_call continuations when the replay cache misses (long sessions) — DeepSeek thinking mode 400 #1193

Description

@gdxnpy

Client or integration

Codex App (also reproduced with a direct /v1/chat/completions client)

Area

Provider adapter

Summary

The #950 fix re-attaches reasoning_content from the in-process replay cache, but that cache is bounded (64 entries / 256 KiB / 1 h TTL, see src/responses/reasoning-replay-cache.ts). When the cache misses on a long session, src/adapters/openai-chat.ts still emits an assistant tool_call history message without reasoning_content, and DeepSeek thinking mode rejects it with HTTP 400:

Provider error 400: Error from provider (Console): Upstream request failed: [invalid_request_error] The `reasoning_content` in the thinking mode must be passed back to the API.

Both affected paths have no fallback when the cache lookup is empty:

  • Main assistant path (openai-chat.ts ~line 348): if (cached.length > 0) { reasoningContent = ... } — when cached.length === 0, the message goes out bare.
  • Orphan-repair path (openai-chat.ts ~line 412): ...(cachedReasoning ? { reasoning_content: cachedReasoning } : {}) — when cachedReasoning is undefined, the synthesized assistant tool_call has no reasoning_content.

Reproduction

  1. Configure the opencode-zen provider with preserveReasoningContentModels: ["deepseek-v4-flash-free"].
  2. Run a long multi-turn tool-calling session with DeepSeek thinking mode (reasoning_effort=max).
  3. Continue a turn whose assistant tool_call history entry lost its reasoning item (compaction, lost assistant turn, or resumed thread) and whose call id is no longer in the replay cache (evicted by >64 entries, >256 KiB, or >1 h TTL).
  4. The request fails with HTTP 400 as above.

Verified conditions:

  • A/B test with the same conversation shape: assistant tool_call message missing reasoning_content -> 400; same shape with a minimal placeholder (" ") -> 200.
  • Failures are intermittent and correlate exactly with cache misses: they appear only when peekReasoningForCall returns nothing for the call id.
  • Reproduced both after >1 h idle and after enough tool rounds to evict the entry.
  • The same session is stable with providers whose upstream tolerates missing reasoning_content (e.g. Kimi), which is why the bug is provider-specific.

Version

2.10.2 (npm @bitkyc08/opencodex); also confirmed present on current main.

Operating system

macOS (darwin, arm64)

Provider and model

opencode-zen / deepseek-v4-flash-free (OpenCode Zen Console, DeepSeek thinking mode)

Logs or error output

Provider error 400: Error from provider (Console): Upstream request failed: [invalid_request_error] The `reasoning_content` in the thinking mode must be passed back to the API.

Redacted configuration

{
  "providers": {
    "opencode-zen": {
      "baseUrl": "https://opencode.ai/zen/v1",
      "preserveReasoningContentModels": ["deepseek-v4-flash-free"]
    }
  }
}

Suggested fix

  • When the replay cache misses for a preserveReasoningContentModels provider, never emit a bare tool_call continuation: inject a minimal placeholder (" ") in both the main assistant path and the orphan-repair path of src/adapters/openai-chat.ts. Verified locally that DeepSeek thinking mode accepts the placeholder (both " " and "..." returned 200), so this closes the 400 deterministically.
  • Longer-term: instead of relying on the bounded in-process side cache, persist the reasoning attachment with the conversation state (e.g. responses-state) so resumed tool loops keep the original reasoning text, or make cache eviction aware of preserveReasoningContentModels call ids.

Checks

  • I searched existing issues and documentation.
  • I removed secrets, tokens, account details, request credentials, and personal data.

Activity

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

    bugSomething isn't workingproviderProvider adapters, OpenAI-compat presets, upstream API quirkstoolstool_calls, MCP, web-search / sidecar tools

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions