Skip to content

Responses carry no request-id header, so proxied Claude Code transcripts have no request id #104

Description

@Nitjsefnie

Description

Responses from the proxy carry no request-id header. Claude Code populates the requestId field of every transcript record from that header, so records written during a proxied session have no request id at all.

Measured on one proxied session against one native Anthropic session on the same machine:

transcript usage-bearing records with requestId
proxied (gpt-5.6-sol) 4 0
native Anthropic 756 753

A transcript legitimately repeats a record, and consumers de-duplicate those repeats by request id. With the field empty they cannot, and totals double. Claude Code's own parse_session.py --cache reported the same 2-request session as:

gpt-5.6-sol  (4 turns)
  input total:       90,482   fresh:      47,986   cache_read:       42,496

against true figures of 2 turns and 23,993 fresh input tokens. Its requestId column shows synthetic (no-req-L15) placeholders for every row.

The response body does carry a unique id (msg_<32 hex>), and for non-streaming responses that value is usable as a substitute key. It is not available in headers for a streaming response, where the id arrives inside the message_start event rather than alongside the response.

Expected Behavior

Every response carries a request-id header holding a value that is stable for one upstream request and distinct across requests, for streaming and non-streaming alike, so Claude Code records a usable requestId and consumers can de-duplicate transcript records.

Reproduction Steps

  1. Start the proxy: CCP_ALIAS_PROVIDER=codex claude-code-proxy serve --port 18765 --no-monitor.
  2. POST an Anthropic-shaped request to http://localhost:18765/v1/messages with a small max_tokens and inspect the response headers: they contain content-type, transfer-encoding and date, with no request-id.
  3. Run any Claude Code session against the proxy with ANTHROPIC_BASE_URL=http://localhost:18765.
  4. Inspect the resulting transcript JSONL and observe no record carries a requestId field.

Environment / Context

claude-code-proxy 0.1.32 (release build, linux-amd64), Claude Code 2.1.226, Linux, codex provider, observed 2026-08-10.

Discovered During

Investigating why per-session token totals from a proxied Claude Code session were exactly double the true values.

Suggested Fix

Unverified. dispatch_request already mints a per-request req_id and threads it through logging and the monitor, and RequestMonitorGuard carries it; it simply never reaches the response. Every response path in src/server.rs funnels through monitor_response_body, which destructures the response parts before the body is streamed, so stamping the header there would cover both streaming and non-streaming responses in one place. Preserving an upstream-supplied request-id rather than overwriting it would avoid relabelling a real provider id with a local uuid.

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

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions