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.

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