Repository navigation
Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
apps/server
Steps to reproduce
- Run a Claude thread and interrupt a turn (Stop), then send another message such as
continue. - Open Usage and look at the Claude model breakdown.
Expected behavior
The model breakdown lists only real models, or anything else in it is explained.
Actual behavior
A model named <synthetic> appears in the Claude usage, with zero tokens and no cost. Nothing in the UI or in docs/user/usage.md says what it is.
Diagnosis
<synthetic> is not a model. Claude Code writes it as message.model on assistant messages it generates locally without calling the API. In the transcripts I checked, every occurrence was the placeholder text No response requested., written after [Request interrupted by user] and before the next prompt. These rows have all token counts at 0:
{"type":"assistant","message":{"model":"<synthetic>","role":"assistant","stop_reason":"stop_sequence","usage":{"input_tokens":0,"output_tokens":0,"cache_creation_input_tokens":0,"cache_read_input_tokens":0}}}The Claude transcript parser keeps any assistant row with a non-empty model name and has no zero-token check, so these rows become a usage bucket:
Pricing already knows about the name and treats it as unpriceable, which is why it shows no cost:
AgentSessionScanner.ts also already ignores it when picking a session's model.
Decision needed
Two ways to resolve this, maintainer's call:
- Exclude it. Skip
<synthetic>rows in the Claude transcript parser so the name never reaches the Usage page. Nothing is lost from the totals, since the rows carry zero tokens and were never billed. - Explain it. Keep the row and add a tooltip on the model name saying it marks messages Claude Code generated locally that were never sent to the API or billed.
Impact
Cosmetic issue
Version or commit
main @ 53456bc
Environment
Linux, Claude Code 2.1.284
Workaround
None needed; the row does not affect token or cost totals.
Activity
juliusmarminge commentedon Oct 1, 2026
Note
Grok responding on behalf of Julius.
Triage
Thanks for the clear diagnosis and for laying out both options, @tris203! I confirmed this on current
main(a3abb52660).<synthetic>isn't a model. Claude Code writes it on assistant messages it makes locally, such asNo response requested.after an interrupted turn, or a local auth or rate-limit notice. Those rows have zero tokens and were never billed.parseClaudeRecordinapps/server/src/usage/usageTranscripts.tsstill keeps any assistant row with a non-emptymessage.model, so the name gets its own bucket in the Claude model breakdown. Pricing already refuses to price it (UNPRICEABLE_MODELSinusagePricing.ts), which is why the cost column says Unpriced and the token count stays at 0. The row leaves the token and cost totals unchanged. It does count toward the "unpriced records" share, though, because that share is based on how many records there are. Web and mobile both show the name exactly as stored, anddocs/user/usage.mddoesn't mention it.Recommendation
I'd go with your first option: exclude it. Session import in
AgentSessionScanner.tsalready skips this placeholder when it picks a session's model, and the usage parser should do the same by dropping<synthetic>inparseClaudeRecord, with aparseClaudeLinetest. A tooltip would put a local placeholder on both web and mobile without telling anyone anything useful about usage. One thing to keep in mind: when a real, billed response contains the textNo response requested., it's stored under the actual model name, so it should still be counted.Codex and Grok already drop zero-token usage events, so this only affects Claude.
Related
--resumes, so every Stop rewrites the full prompt cache (not covered by #10689) #10955 (open issue, about Stop rewriting the Claude prompt cache) or fix(server): update all Claude unified usage windows #14441 (open PR, about Claude usage windows).modelUsagetelemetry, which is a different problem.fix(usage): Claude usage no longer lists a `<synthetic>` model
fix(usage): Claude usage no longer lists a `<synthetic>` model
fix(usage): Claude usage no longer lists a `<synthetic>` model
fix(usage): Claude usage no longer lists a `<synthetic>` model