Skip to content

fix: forward client headers in native passthrough mode#586

Open
zerray wants to merge 1 commit intodecolua:masterfrom
zerray:fix/passthrough-headers
Open

fix: forward client headers in native passthrough mode#586
zerray wants to merge 1 commit intodecolua:masterfrom
zerray:fix/passthrough-headers

Conversation

@zerray
Copy link
Copy Markdown

@zerray zerray commented Apr 14, 2026

Summary

  • In native passthrough mode (e.g. Claude Code → Claude API), 9router was rebuilding request headers from static config + cached values instead of forwarding the client's original headers
  • This caused extra anthropic-beta flags (e.g. token-efficient-tools-2026-03-28) to be injected into upstream API requests via the union merge logic in DefaultExecutor.buildHeaders, even though the client never sent them
  • The extra beta flags altered model behavior, causing unicode encoding anomalies in tool call arguments (e.g. u8fd9 instead of in partial_json deltas)

Changes

open-sse/executors/base.js

  • Added buildPassthroughHeaders() method that starts from the client's original headers, strips hop-by-hop headers, swaps auth credentials, and ensures the oauth-2025-04-20 beta flag when using OAuth
  • Updated execute() to accept passthrough and clientHeaders params, using buildPassthroughHeaders when both are present

open-sse/handlers/chatCore.js

  • Passes passthrough flag and clientRawRequest.headers to executor.execute() at both call sites (initial request + retry-after-refresh)

Root cause

The static Anthropic-Beta header in providers.js includes flags like token-efficient-tools-2026-03-28 that are not present in Claude Code's own requests. The header merge logic (union of static + cached flags) injected these into every upstream request. With this fix, passthrough requests forward the client's exact headers — only auth is swapped.

Test plan

  • Verified with Claude Code 2.1.97 → cc/claude-opus-4-6 passthrough: Chinese unicode characters now render correctly in tool call arguments
  • Non-passthrough requests continue to use buildHeaders() with static config as before
  • OAuth access token requests get oauth-2025-04-20 beta flag injected automatically

🤖 Generated with Claude Code

… flags

In native passthrough (claude-to-claude), 9router was rebuilding request
headers from static config + cached values, injecting extra anthropic-beta
flags (e.g. token-efficient-tools) that the client never sent. This caused
the upstream Claude API to behave differently, leading to unicode encoding
anomalies in tool call arguments.

Now in passthrough mode, the client's original headers are forwarded
directly — only auth is swapped and oauth beta flag ensured.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant