fix(haiku): pass prompt on stdin, not argv — saves of long sessions die with E2BIG#107
Conversation
…ions) call_haiku passed the full prompt as a single argv string (claude -p <prompt>). Linux caps one argument at MAX_ARG_STRLEN (131072 bytes = 128KB), so a prompt at or above that size fails at exec() with OSError [Errno 7] "Argument list too long" — surfaced as RuntimeError and the save is lost. The failure is silent (log only) and permanent for that session, since the extract only grows. It hits exactly the sessions worth capturing: long ones, recovery of a missed session, and any accumulated delta over 128KB. claude -p reads the prompt from stdin when no positional prompt is given, so pass it via subprocess input= instead. stdin has no argv size limit; no behavior change for normal-size prompts. Adds a regression test asserting the prompt arrives via input= and is absent from the command argv (it fails against the old argv form). Repro: subprocess.run(["/bin/true", "x"*131072]) raises E2BIG; the same payload via input= on stdin runs fine.
fdaviddpt
left a comment
There was a problem hiding this comment.
Clean fix — and a nasty bug well caught.
The failure mode is the scary part: extracts only grow, so once a session crosses 128KB every subsequent save dies, silently (just a log line). That hits exactly the long sessions a memory tool most wants to keep.
The fix is correct and minimal — claude -p reads stdin with no positional, subprocess.run(input=...) uses communicate() so no deadlock, and there's no behavior change for normal-size prompts. Bonus: prompt no longer shows up in the process list.
The test earns its keep too — guards both halves (prompt in input=, absent from argv) and fails against the old form, so the regression can't sneak back. Nice catch on the old tests being blind to it.
Thanks Kevin — repro without an API call, exact threshold, real-env validation on a ~1.9MB extract. That's how a bug fix should read. 🙏
Summary
call_haikupasses the entire prompt as a single command-line argument (claude -p <prompt>). On Linux a single argv string is capped atMAX_ARG_STRLEN(131072 bytes = 128 KB =PAGE_SIZE * 32). When a session's extract reaches that size,subprocess.runfails atexec()withOSError: [Errno 7] Argument list too long, which surfaces as aRuntimeErrorand the save is lost.The failure is silent (only a log line) and permanent for that session — the extract only grows, so every subsequent save fails the same way. It strikes exactly the sessions a memory tool most wants to capture: long ones, recovery of a missed session, or any accumulated delta over 128 KB.
Root cause
pipeline/haiku.py:Reproduction (no API call needed — it fails at exec)
Threshold is exact: 131071 bytes argv → ok, 131072 bytes (128 KB) → E2BIG.
Fix
claude -preads the prompt from stdin when no positional prompt is given. Drop the positional and pipe viainput=:stdin has no size limit, so prompts of any length deliver. No behavior change for normal-size prompts.
Testing
test_call_haiku_sends_prompt_on_stdin_not_argv— asserts the prompt is passed viainput=and is absent from the command argv. It passes on this change and fails against the old argv form (the existing tests were blind to it: they checkedcmd[0]andenv, neverinput=), so the regression can't silently return.tests/test_haiku.pynow 31/31.call-haiku error: [Errno 7] Argument list too longbefore the change, and completed normally (Haiku returned a summary, entry written) after it.Risk
Minimal.
subprocess.run(..., input=, capture_output=True)usescommunicate()internally, so there is no stdin/stdout deadlock.inputis astrconsistent withtext=True/encoding="utf-8".Not changed
Scope is the single argv→stdin swap. No change to flags, parsing, env stripping, or token accounting.