Intermittent: piped -p prompt is enqueued and recorded in the transcript but never reaches the model - session answers an empty user turn

Status Open
Reported on v2.1.233
Maintainer reply None cached
Activity 0 comments · opened Aug 17, 2026

Environment: Claude Code CLI 2.1.233, Windows 11 Pro 10.0.26200, claude -p via type file | claude -p --model sonnet from cmd wrappers (the sweep wrapper adds --output-format json; the parse wrapper does not — both reproduce, fired by Task Scheduler and a Python dispatcher). Entrypoint recorded as sdk-cli.

Summary: On affected days (08/12, 08/13, 08/15), roughly 25–47% of our headless sweep fires — depending on the denominator; exact counts under Repro — complete in 1–2 turns with a tiny improvised response instead of executing the piped prompt. The session transcript shows the full prompt was delivered — a queue-operation enqueue/dequeue pair followed by a type:"user" message containing the complete piped prompt text (~14KB in the sweep lane, ~28KB in the parse lane) — but the usage telemetry for the assistant turn proves the request the model actually received did not contain it.

Evidence (four failing runs vs healthy controls, same wrappers, same prompt bytes):

| run | session | num_turns | input_tokens | cache_creation | cache_read | total ctx | output |
|---|---|---|---|---|---|---|---|
| sweep 08-15 20:06 | 3cc7c41f | 1 | 2 | 0 | 64,827 | ~64.8K | "Comms sweep: quiet." (13 tok) |
| sweep 08-15 20:41 | b3ff24d1 | 1 | 2 | 0 | 64,827 | ~64.8K | same 13 tokens |
| sweep 08-15 22:01 | 8256cde3 | 1 | 2 | 0 | 64,808 | ~64.8K | a greeting improvised from CLAUDE.md (26 tok) |
| parse 08-16 06:47 | 868b0918 | 2 | 2 | 40,334 | 29,401 | ~69.7K | ran an unrelated CLAUDE.md procedure |
| healthy sweep 08-15 21:26 | 55fa30d6 | 18 | 2 | 21,476 | 131,581 | ~153K | full task executed |
| healthy sweep 08-15 21:11 | e20fceda | 36 | 2 | 169 | 125,657 | ~125.8K | full task executed |

Usage cells are the first API request of each session (iterations[0] in the result JSON — the request that should have carried the prompt); for the single-turn failing rows this equals the session totals.

  • The failing turns are ~60–88K tokens smaller than healthy turns of the same wrapper piping the same file minutes apart — the missing content includes the entire piped prompt. input_tokens: 2 with zero cache creation on the failing sweep turns means essentially nothing new was sent; the failing parse run's 40,334 cache-creation tokens are its ambient context being written to cache for the first time that morning, still without the prompt.
  • Two failing runs 35 minutes apart read a byte-identical 64,827-token cached prefix — the "starved" request is deterministic, not garbage.
  • The failing sweep turns show zero thinking tokens and zero tool use (the failing parse run made a single ToolSearch call on its first turn, with zero thinking tokens; its second turn spent 255 thinking tokens answering, improvising a user-level CLAUDE.md procedure); the model's outputs are exactly what a session with only the ambient CLAUDE.md context would improvise (in one case it verbatim executed a CLAUDE.md session-open instruction that the delivered prompt explicitly overrides).
  • The transcript in every failing case records the full prompt as the user message (and in the last-prompt preview), so transcript inspection alone misdiagnoses this as the model "ignoring" instructions.

Expected: the enqueued prompt is included in the first API request, or the run fails loudly.

Actual: the run exits 0 having answered an empty user turn; only output-contract checking downstream catches it.

Impact: every -p automation lane needs an output-contract watchdog to detect silently-instruction-less runs; prompt-side mitigations are ineffective because the model never receives the text.

Repro: no deterministic trigger found; no occurrences on the other days in the visible log window (one earlier candidate — a 1-turn, input_tokens: 2 run on 08/02 — predates a wrapper guard we added against empty stdin pipes and was attributed to that at the time, so it can't be cleanly counted either way). Frequency on affected days, counting result-JSON log entries carrying the failure signature (num_turns:1, input_tokens:2, tiny improvised output, is_error:false): the worst single lane (the sweep wrapper above) failed 3 of 7 fires (43%) on 08/12, 4 of 11 (36%) on 08/13, and 7 of 15 (47%) on 08/15; fleet-wide across all three sweep lanes (three agent identities, same wrapper pattern) it is 3 of 12 (25%), 4 of 32 (12.5%), and 7 of 26 (27%) on those days — the other two lanes show zero silent failures, their only 1-turn entries being loud is_error:true API errors on 08/16. The second, independent wrapper (the parse lane) failed its single 08/16 fire. Happy to provide the full JSONL transcripts of the failing sessions.

View original on GitHub ↗