JuliusBrussee/caveman · error

cave_sandbox_input_limit

cave_sandbox_input_limit

Error message

cave_sandbox_input_limit

What it means

The sandbox tool worker reads its request frame from stdin and enforces a hard 1,048,576-byte (1 MiB) limit; exceeding it throws cave_sandbox_input_limit before any parsing. The cap bounds worker memory and keeps the length-prefixed protocol cheap — oversized tool params are rejected up front rather than buffered.

Source

Thrown at packages/agent/src/tool-worker.ts:81

  process.exit(1);
});

async function readRequest(): Promise<{
  entry: string;
  agentPath: string[];
  rootDefinitionSha256: string;
  toolDefinitionSha256: string;
  tool: string;
  params: unknown;
  allowSideEffects: boolean;
  allowNetwork: boolean;
}> {
  const chunks: Buffer[] = [];
  let size = 0;
  for await (const chunk of stdin) {
    const buffer = Buffer.from(chunk);
    size += buffer.byteLength;
    if (size > 1_048_576) throw new Error("cave_sandbox_input_limit");
    chunks.push(buffer);
  }
  return JSON.parse(Buffer.concat(chunks).toString("utf8"));
}

try {
  const request = await readRequest();
  if (typeof request.entry !== "string" || !Array.isArray(request.agentPath) ||
      request.agentPath.length > 8 ||
      request.agentPath.some((item) => typeof item !== "string" ||
        !/^[a-zA-Z][a-zA-Z0-9_-]{0,127}$/.test(item)) ||
      typeof request.rootDefinitionSha256 !== "string" ||
      !/^[a-f0-9]{64}$/.test(request.rootDefinitionSha256) ||
      typeof request.toolDefinitionSha256 !== "string" ||
      !/^[a-f0-9]{64}$/.test(request.toolDefinitionSha256) ||
      typeof request.tool !== "string" ||
      !/^[a-zA-Z][a-zA-Z0-9_-]{0,127}$/.test(request.tool) ||
      typeof request.allowSideEffects !== "boolean" ||

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Pass a file path (or digest/reference) instead of inline content, and let the sandboxed tool read the file itself.
  2. Trim or chunk params so the JSON-serialized frame stays well under 1 MiB.
  3. Move large payloads into the entry/definition bundle rather than the per-invocation request.

Example fix

// before
const out = await tool({ data: hugeBase64String }); // > 1 MiB frame

// after
await fs.writeFile(tmp, hugeBase64String);
const out = await tool({ dataPath: tmp });
Defensive patterns

Strategy: validation

Validate before calling

const INPUT_LIMIT = 1_048_576;
function withinSandboxInputLimit(request: unknown): boolean {
  const size = Buffer.byteLength(JSON.stringify(request) ?? "", "utf8");
  return size <= INPUT_LIMIT;
}
if (!withinSandboxInputLimit(frame)) throw new Error("params too large for sandbox worker");

Try / catch

try {
  await invokeSandboxedTool(frame);
} catch (error) {
  if (error instanceof Error && error.message === "cave_sandbox_input_limit") {
    // do not retry the same payload: pass a file reference instead of inline data
  } else throw error;
}

Prevention

When it happens

Trigger: A sandboxed tool invocation whose serialized request frame (entry, agentPath, digests, tool name, and especially params) exceeds 1 MiB — e.g. passing a huge document, base64 blob, or large array as tool arguments.

Common situations: Feeding whole files or logs into a sandboxed tool's params instead of reading them inside the sandbox; pasting large inline data because the tool has no file-path parameter.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/d546126d385809cf. Report an issue: GitHub.