Session-start sidecar request is issued twice concurrently and both are billed

Status Open
Maintainer reply None cached
Activity 1 comment · opened Aug 18, 2026

Summary

At session start, the CLI issues the same sidecar request twice, concurrently — a few milliseconds apart, while the first is still in flight. Both requests reach the API, both are answered, and both are billed. It is not a retry and not a cache miss: it is one question answered twice.

Cheap per instance. Reporting it as a structural defect rather than a cost problem.

How it was observed

A local forward proxy that captures request and response bytes before any of its own processing runs. Because the capture is written pre-pipeline, the duplicate is visible as the client's own bytes rather than as anything the proxy introduced.

The population (measured 2026-08-14)

Across the capture corpus on that date: 118 duplicate request streaks, 62 double-billed, of which 47 form one tight class:

  • model claude-haiku-4-5, one message, max_tokens=32000
  • every instance at session start (capture lines 3–5)
  • inter-send interval 6–25 ms, median 14 ms

Model, position in the session, and interval are three independent axes, and they partition the population identically — which is what makes this one class rather than a sort order.

Both sends are real, completed calls. All 47 pairs carry distinct upstream request-ids, none null, and each member joins to its own usage record with a real final output-token count. The two answers land within a token or two of each other (16|16, 18|18, 19|19, 26|29).

It cannot be a retry, and that is measured rather than argued. The first send's own wall time to its first usage record is ~700–800 ms. The duplicate is issued 6–25 ms in. On 47 of 47 pairs the second request left before anything about the first could have been observed — there was nothing to retry yet.

Cost: 48,203 input-side tokens attributable to the duplicate sends across that corpus.

Relationship to #78420 — related symptom, different shape

I read #78420 before writing this, and this is not the same mechanism, so it should not be read as confirming that report:

| | #78420 | this |
|---|---|---|
| shape | one request whose prefix is assembled ~2x | two separate requests, byte-identical |
| when | mid-session, at 400–700k contexts | session start, first few requests |
| model reported | opus, 1M context | claude-haiku-4-5 |
| evidence of the extra call | inferred from cache_read ≈ 2.00x with negligible cache_creation | both calls directly observed, each with its own request-id and usage record |
| scale | up to 1.37M tokens in one request | 6–25 ms apart, small sidecar payloads |

Both are "requests the user did not ask for, billed to the user", which is why they are worth reading together. The evidence here does not speak to whether #78420's doubling is the same root cause, and I am not claiming it does.

What we did NOT check

Stated so the verified parts are believable:

  • Whether this reproduces without a proxy in the path. The duplicate appears in pre-processing captures, which rules the proxy out as its source, but does not prove the proxy is irrelevant to timing.
  • Which client-side code path issues the second send.
  • Whether the behaviour varies by platform, CLI version, or account type — this is one machine.
  • The population has not been re-measured since 2026-08-14, and cannot be from this corpus: our proxy has coalesced this class since that date, so the class is absent by construction now. The numbers above are the pre-mitigation measurement, given with their date rather than presented as current.

A note on the obvious fix

Dropping the second send is not available to a proxy — two client requests are in flight and each is owed a response. The only safe shape we found was coalescing one upstream call to both callers.

Flagging this only because "just dedupe adjacent identical requests" reads as the low-risk change and is not one: there is a separate mid-session duplicate class where the second send is a genuine retry, and suppressing it there would leave a real retry unanswered. Whatever is done client-side presumably has better information available than a proxy does.

---

🤖 Generated with Claude Code

https://claude.ai/code/session_01HpyfVmjyFWyze7LtcfxqC3

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗