-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
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
- Configure CLIProxyAPI with both Gemini CLI OAuth (
cliproxyapi -login) and Claude OAuth (cliproxyapi -claude-login) - Launch Claude Code with
ANTHROPIC_BASE_URLpointing to CLIProxyAPI (http://127.0.0.1:8317) - Start a conversation using a Gemini model (e.g.,
/model gemini-3-pro-preview) - Send a few messages to build up conversation history
- Switch to a Claude model mid-conversation (e.g.,
/model claude-opus-4-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:
- Convert to
redacted_thinkingtype — Claude's API accepts redacted thinking blocks without signature validation - Strip thinking blocks from previous turns that originated from non-Claude providers
- 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-preview→claude-opus-4-6 - Client: Claude Code CLI
Related Issues
- Gemini-3-pro-high Corrupted thought signature #1538 — Gemini-3-pro-high corrupted thought signature (Antigravity-specific)
- bug: Invalid signature in thinking block (API 400) on follow-up requests #1398 — Invalid signature in thinking block on follow-up requests (closed/fixed)
- fix(antigravity): prevent corrupted thought signature when switching models #994 — Fix corrupted signature when switching models (closed/fixed)
Those fixes addressed Antigravity-specific scenarios but do not cover the Gemini CLI OAuth → Claude OAuth switching case.