Skip to content

bug: Invalid thinking block signature when switching from Gemini CLI to Claude OAuth mid-conversation #1584

@CF-Developers

Description

@CF-Developers

Description

When using CLIProxyAPI with both Gemini CLI OAuth and Claude OAuth providers, switching from a Gemini model to a Claude model mid-conversation causes a 400 invalid_request_error due to invalid thinking block signatures.

Steps to Reproduce

  1. Configure CLIProxyAPI with both Gemini CLI OAuth (cliproxyapi -login) and Claude OAuth (cliproxyapi -claude-login)
  2. Launch Claude Code with ANTHROPIC_BASE_URL pointing to CLIProxyAPI (http://127.0.0.1:8317)
  3. Start a conversation using a Gemini model (e.g., /model gemini-3-pro-preview)
  4. Send a few messages to build up conversation history
  5. Switch to a Claude model mid-conversation (e.g., /model claude-opus-4-6)
  6. Send a message

Expected Behavior

The conversation should continue seamlessly with the Claude model, with CLIProxyAPI handling the provider transition transparently.

Actual Behavior

Claude's API returns a 400 error:

API Error: 400 {"type":"error","error":{"type":"invalid_request_error","message":"messages.3.content.0: Invalid `signature` in `thinking` block"},"request_id":"req_011CY5rpLDkzLmojWXnJH1ML"}

Root Cause

When Gemini responds through CLIProxyAPI, the proxy wraps responses in Claude-format thinking blocks with proxy-generated signatures. These signatures are not cryptographically valid (only Anthropic's servers can produce valid ones). When the user switches to a real Claude model, the conversation history containing these fake-signed thinking blocks is sent to Anthropic's API, which validates the signatures and rejects the request.

Suggested Fix

When routing a request to Claude and the conversation history contains thinking blocks from a non-Claude provider (Gemini CLI, etc.), CLIProxyAPI should either:

  1. Convert to redacted_thinking type — Claude's API accepts redacted thinking blocks without signature validation
  2. Strip thinking blocks from previous turns that originated from non-Claude providers
  3. Remove signatures from thinking blocks that were not generated by Claude's API

Option 1 (redacted_thinking) is likely the cleanest approach as it preserves the conversation structure while avoiding signature validation.

Environment

  • CLIProxyAPI Version: 6.8.15 (Homebrew)
  • OS: macOS (Darwin 25.2.0, arm64)
  • Providers: Gemini CLI OAuth + Claude OAuth (Max plan)
  • Models tested: gemini-3-pro-previewclaude-opus-4-6
  • Client: Claude Code CLI

Related Issues

Those fixes addressed Antigravity-specific scenarios but do not cover the Gemini CLI OAuth → Claude OAuth switching case.

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