[Bug] OTel claude_code.user_prompt only emitted for slash-command dispatches; regular prompt submissions emit no event
Bug Description
claude_code.user_prompt is only emitted for slash-command dispatches. Regular typed prompt submissions emit no event.
Version: 2.1.220
Last known good: 2.1.206 (verified by hand — see below)
On 2.1.220, every user_prompt event carries a command_name (builtin: exit/mcp/bug, or custom) with prompt_length 4–5 — i.e. the slash command string. Interactive sessions with dozens of typed prompts produce zero events for those prompts.
On 2.1.206, user_prompt events have no command_name and prompt_length values of 49–611 chars, one per submitted prompt.
Same fleet, same collector, same 3-day window. Not terminal-dependent — reproduced on ghostty, Apple_Terminal, and non-interactive. All other events flow normally (~50k / 3 days).
Bisect: 2.1.206 verified good by running it directly on the same machine with the same collector and env. 2.1.211 was reported good from fleet telemetry only, not hand-tested — so the regression window is 2.1.206 → 2.1.220, possibly narrower.
The turns themselves are fine. prompt.id is populated on all other events in affected 2.1.220 turns, so the prompt reaches the client and the turn executes normally — only this one emit is skipped.
No error surfaces. Telemetry init is healthy ([3P telemetry] Event logger set successfully, First logs export: SUCCESS in ~/.claude/debug/), and no [3P telemetry] Event dropped warning appears. The drop is silent, which is why the Errors block below is empty.
Effect: user_prompt.count measures slash-command usage, not prompt volume. Any dashboard or alert built on prompt volume is silently reading near-zero.
Environment Info
- Platform: darwin
- Terminal: ghostty (also reproduced: Apple_Terminal, non-interactive)
- Version: 2.1.220
- Feedback ID: e5e6afa7-e410-445f-a678-633d25166024
Errors
[]Showing cached comments. Read the full discussion on GitHub ↗
4 Comments
Update: bisected locally, and confirmed the turns are otherwise intact.
Ran 2.1.206 directly (
~/.local/share/claude/versions/2.1.206) against the same collector with the same env: typed prompts emituser_promptnormally, realisticprompt_length, nocommand_name. 2.1.220 on the same machine, same config, emits nothing for typed prompts. Regression window is 2.1.206 → 2.1.220. (The "last known good: 2.1.211" in the original report came from fleet telemetry; 2.1.206 is the one I've verified by hand.)prompt.idis populated on all other events in the affected 2.1.220 turns — so the prompt arrives, the turn runs, and every other event in that turn exports fine. Only theuser_promptemit is skipped. Telemetry init is clean in~/.claude/debug/(Event logger set successfully,First logs export: SUCCESS) with noEvent droppedwarning, so this isn't a logger or exporter problem.Narrowing where it broke: both versions route the slash path and the typed-prompt path through the same emitter. The slash site emits unconditionally; the typed site is guarded:
That guard is present in 2.1.206 too, so the guard isn't the change — what's passed to it is. In 2.1.220 the call is
RPp(x, N, P, Y, ...), whereNis the processed content-block array assembled immediately above (N.push(oe.block)) andxis the pre-processing input. The message is constructed from the second parameter, which is why the turn works; the emit reads the first,fcomes back"", and the event is skipped. The 2.1.206 call site passes the processed value in that position.Bundles are minified, so parameter identities are inferred rather than read from sourcemaps — but it accounts for the whole symptom set: typed prompts silently skip only this event on every surface, slash commands are unaffected, other events in the same turn flow normally, and nothing errors.
Example of an event that does arrive —
/mcp,prompt_length: "4", in a session where typed prompts produced nothing:Confirming this on our fleet (multiple Team orgs, a wide spread of client versions in flight concurrently). Two things to add: a narrower window, and a second event class.
Window: 2.1.212 → 2.1.220. Non-command
user_promptevents arrive from every version up to and including 2.1.212. The lowest non-emitting version we have data for is 2.1.220. That rules out 2.1.206–2.1.212. We can't resolve 2.1.213–2.1.219; not enough of those in the fleet.claude_code.assistant_responseis gone at the same boundary. Every event of that type in our data comes from 2.1.193–2.1.212, none above — and 2.1.193 is the version that introduced the event. On one account running 2.1.226–2.1.232, over a week:api_request,tool_decisionandtool_resultall flowing normally in the thousands; everyuser_promptcarrying acommand_name;assistant_responsecount exactly zero.Same signature you describe: the turn runs, every other event in it exports, only the content-bearing emit is skipped, nothing errors. If the cause is a call site passing the pre-processing value, there's plausibly a second site with the same problem.
Not surface-specific, and not local config. Identical cut in
claude-code,claude-code-desktopandcowork. Cowork is the useful one: its OTEL config comes from the admin console rather than env vars ormanaged-settings.json, so local configuration can be ruled out as a factor.Practical effect: prompt and response telemetry degrades to zero as a fleet upgrades, silently. We only caught it because stragglers on older versions were still reporting — the drop is invisible if your whole fleet is current.
Happy to file the
assistant_responsehalf as its own issue if you'd rather track it separately.Thanks for the detailed report. I tried to reproduce this on the released 2.1.233 (macOS) by pointing the CLI at a local OTLP/HTTP collector (
CLAUDE_CODE_ENABLE_TELEMETRY=1 OTEL_LOGS_EXPORTER=otlp OTEL_EXPORTER_OTLP_PROTOCOL=http/json) and running both a non-interactiveclaude -p "..."and an interactive session where I typed a prompt and then/exit.In both cases
claude_code.user_promptwas emitted for the typed prompt (prompt_length72–93,prompt.idset, nocommand_name) as well as for/exit(prompt_length5,command_name=exit). Same result on 2.1.227. So I can't reproduce a typed-prompt drop on the current release, and reading the client code the emit for typed prompts is unconditional.One difference: since ~2.1.21x the typed-prompt
user_promptrecord carries an extramessage.uuidattribute (and, when a trace is active, trace context), which the slash-command record does not — if your collector or backend applies an attribute schema, that could explain why only those records disappear.To dig further, could you share: which exporter protocol/collector you use (grpc vs http/protobuf vs http/json, collector type and any processors/filters), your
OTEL_*/CLAUDE_CODE_*env, whether it still happens on 2.1.233,claude doctoroutput, and ideally a test against a raw local OTLP receiver (no processors) — does the typed-prompt record show up there?🤖 Generated with Claude Code
We weren't able to reproduce this. Could you provide steps to trigger the issue — what you ran, what happened, and what you expected? This issue will be closed automatically if there's no activity within 7 days.