JuliusBrussee/caveman · error
hook payload too large
Error message
hook payload too large
What it means
The native fast hook reads the agent's hook payload (tool-call JSON) from stdin with a hard 2 MiB cap to keep the hot path cheap and avoid unbounded memory. When accumulated chunk bytes exceed 2*1024*1024 the read loop aborts with this error. It is a deliberate resource guard, not a parsing failure.
Source
Thrown at packages/cli/src/native-hook-fast.ts:100
if (explicit !== undefined && explicit !== "") return explicit === "safe" || explicit === "max" || explicit === "record" ? explicit : "record";
const mode = configuredMode();
return mode === "record" ? "record" : mode === "pixel" ? "max" : "safe";
}
function profile(): NativeProfile {
const explicit = process.env.CAVEMAN_NATIVE_PROFILE?.trim().toLowerCase() as NativeProfile | undefined;
if (explicit) return PROFILES.has(explicit) ? explicit : "record-only";
const mode = policyMode();
return mode === "record" ? "record-only" : mode === "max" ? "full-max" : "full-safe";
}
async function stdin(): Promise<Buffer> {
const chunks: Buffer[] = [];
let bytes = 0;
for await (const chunk of process.stdin) {
const value = Buffer.from(chunk);
bytes += value.length;
if (bytes > 2 * 1024 * 1024) throw new Error("hook payload too large");
chunks.push(value);
}
return Buffer.concat(chunks);
}
function bounded(value: unknown, max = 160): string | undefined {
if (typeof value !== "string") return undefined;
const clean = value.replace(/[\r\n\0]/g, " ").trim();
return clean ? clean.slice(0, max) : undefined;
}
function digestObject(value: unknown): { bytes: number; sha256: string } | undefined {
if (value && typeof value === "object" && !Array.isArray(value)) {
const candidate = value as Record<string, unknown>;
if (typeof candidate.bytes === "number" && candidate.bytes >= 0 && typeof candidate.sha256 === "string" && /^sha256:[0-9a-f]{6,64}$/i.test(candidate.sha256)) {
return { bytes: Math.floor(candidate.bytes), sha256: candidate.sha256.toLowerCase() };
}
}View on GitHub (pinned to 27d5a3981a)
Solutions
- Reduce the payload: have the tool input reference files by path instead of inlining megabytes of content.
- Filter hook events: configure the agent's hook matcher so only the event names you need are delivered to the native hook.
- If you control the producer, chunk or truncate large fields before they reach the hook process.
- Do not attempt to raise the cap by patching; it is compiled into the guard — restructure the payload instead.
Example fix
// before: tool input inlines a 5 MiB string
{ "tool_input": { "content": "<5 MiB of text>" } }
// after: reference by path
{ "tool_input": { "path": "large-file.txt" } } Defensive patterns
Strategy: validation
Validate before calling
// Producer side: keep hook events small before they reach the native hook
function assertPayloadSize(json: unknown): void {
const bytes = Buffer.byteLength(JSON.stringify(json) ?? "");
if (bytes > 2 * 1024 * 1024) {
throw new Error(`hook payload ${bytes}B exceeds 2 MiB; trim tool_input content`);
}
} Try / catch
try {
const payload = await stdin();
} catch (e) {
if (e instanceof Error && e.message === "hook payload too large") {
process.exit(0); // treat oversized event as no-op: never fail the agent's tool call
}
throw e;
} Prevention
- Reference large content by path in tool inputs instead of inlining it.
- Scope hook matchers to the specific events the hook needs (avoid forwarding everything).
- Treat the 2 MiB cap as a contract when designing custom tools for agents.
When it happens
Trigger: An agent emits a hook event (e.g. PreToolUse/PostToolUse JSON) whose serialized payload exceeds 2 MiB — typically huge file writes, enormous command strings, or massive tool outputs embedded in the event.
Common situations: Write/Edit tools with multi-megabyte file contents, pasted base64 blobs, agents streaming giant diffs through hooks, or a misconfigured hook that forwards whole conversation transcripts.
Related errors
- cave_harness_upstream_version_invalid
- cave_harness_artifact_digest_invalid
- cave_harness_request_invalid
- cave_sandbox_input_limit
- option not found
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/342fa956f11c86d0.
Report an issue: GitHub.