Spill large system prompts to a file to avoid execve E2BIG - #59
Merged
Merged
Conversation
The Claude Agent SDK passes the system prompt inline as a single CLI
argument (--system-prompt <STRING>). Linux limits one argv element to
MAX_ARG_STRLEN = PAGE_SIZE * 32 = 131,072 bytes. Workspaces that combine
SOUL.md, TASK.md, AGENTS.md, TOOLS.md, MEMORY.md, the skill summaries,
and 8 recalled memU summaries can easily cross that boundary, causing
execve() to return E2BIG ("Argument list too long") and Claude Code to
fail to start with CLIConnectionError.
Switch to the SDK's --system-prompt-file mechanism (SystemPromptFile)
when the assembled prompt exceeds 100 KB. The file is written under
<workspace>/.nerve/cache/system_prompts/<session_id>.md with a lazy GC
that drops files older than 7 days on each write. Small prompts continue
to be passed inline so prompt-caching prefix hits are unaffected.
pufit
approved these changes
Apr 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The
clickhouse-ci-task-workercron started failing with:at every invocation, regardless of which task it picked.
Root cause
Linux limits a single
argvelement toMAX_ARG_STRLEN = PAGE_SIZE * 32 = 131,072 bytes. The Claude Agent SDK passes the system prompt inline as one argument (subprocess_cli.py):build_system_prompt()concatenatesSOUL.md+TASK.md+AGENTS.md+TOOLS.md+ the first 300 lines ofMEMORY.md+ session context + skills section + 8 pre-recalled memU summaries.Measured on a real worker workspace today:
task_domain,infrastructure,contactsare multi-KB each)Result:
execve()returnsE2BIGand the subprocess never starts.Fix
The SDK already supports
--system-prompt-fileviaSystemPromptFile = {"type": "file", "path": ...}. Switch to it when the assembled prompt exceeds 100 KB (well under the kernel limit, leaves headroom for env/argv overhead). Small prompts still go inline so prompt-caching prefix hits are unaffected.The file is written to
<workspace>/.nerve/cache/system_prompts/<session_id>.md. Resumes pick up the same path without re-writing. A lazy GC on each write deletes files older than 7 days.Test plan
.venv/bin/pytest tests/ -v)clickhouse-ci-task-workernow starts cleanly with the file-based path (log showsSession ...: system prompt N bytes (> 100000), passing via file ...)