JuliusBrussee/caveman · error
cave_sandbox_source_staging_root_required
cave_sandbox_source_staging_root_required
Error message
cave_sandbox_source_staging_root_required
What it means
commonAncestorDir throws this when its paths array is empty (dirs[0] is undefined). In the production flow it is only reached from sandboxSourceReadFlags after the >1024-file threshold, which implies a non-empty list, so an empty array here means an internal invariant broke: the flag-collapse path executed with zero staged source files. It is a defensive guard, not a configuration error surface.
Source
Thrown at packages/agent/src/runtime.ts:4887
await rm(workspace, { recursive: true, force: true });
}
}
/**
* Above this many per-file `--allow-fs-read` flags, collapse the staged source
* files to their common ancestor directory. A large project would
* otherwise blow the OS argument limit (E2BIG) and the tool could not spawn at
* all. The collapse is safe here: `sourceFiles` are paths inside the per-run
* STAGED COPY, which already contains only the reachable source graph — never
* the real project root with its .env and credentials.
*/
const SANDBOX_FS_READ_FLAG_THRESHOLD = 1024;
function commonAncestorDir(paths: readonly string[]): string {
const dirs = paths.map((path) => resolve(dirname(path)));
const first = dirs[0];
if (first === undefined) {
throw new Error("cave_sandbox_source_staging_root_required");
}
let ancestor = first;
while (dirs.some((path) => escapesRoot(relative(ancestor, path)))) {
const parent = dirname(ancestor);
if (parent === ancestor) {
throw new Error("cave_sandbox_source_read_root_refused");
}
ancestor = parent;
}
if (dirname(ancestor) === ancestor) {
throw new Error("cave_sandbox_source_read_root_refused");
}
return ancestor;
}
export function sandboxSourceReadFlags(
sourceFiles: readonly string[],
stagingRoot?: string,View on GitHub (pinned to 766dce6b13)
Solutions
- Ensure the tool declares at least one source file before computing read flags
- If invoking sandboxSourceReadFlags directly, guard the empty list yourself or stay under SANDBOX_FS_READ_FLAG_THRESHOLD (1024)
- If hit through the public API, report it as a bug: the executor should never collapse an empty graph
Defensive patterns
Strategy: validation
Validate before calling
// Guard the empty list before computing collapsed read flags
function safeSourceReadFlags(sourceFiles: readonly string[], stagingRoot?: string) {
if (sourceFiles.length === 0) return []; // nothing to grant; avoids the invariant throw
return sandboxSourceReadFlags(sourceFiles, stagingRoot);
} Type guard
function hasSourceFiles(files: readonly string[]): boolean {
return Array.isArray(files) && files.length > 0 && files.every((f) => typeof f === 'string' && f.length > 0);
} Try / catch
try {
flags = sandboxSourceReadFlags(sourceFiles, stagingRoot);
} catch (error) {
if (error instanceof Error && error.message === 'cave_sandbox_source_staging_root_required') {
// empty list at collapse time: internal invariant - report with the file list
}
throw error;
} Prevention
- Never invoke the flag builder with an empty sourceFiles array
- Ensure tools declare at least one source file when they expect staged sources
- Prefer the public sandbox executor over importing the internals directly
When it happens
Trigger: Directly calling sandboxSourceReadFlags/commonAncestorDir with an empty sourceFiles array in tests or internal tooling; a tool definition whose staged source graph is empty by the time the collapse runs (internal bug).
Common situations: Unit tests exercising the collapse helpers without fixtures; custom integrations importing the internals rather than going through the sandbox executor; effectively unreachable through the public run API.
Related errors
- cave_sandbox_source_read_root_refused
- caveman agent: dev ${kind} escapes project root
- caveman agent: dev ${kind} symlink escapes project root
- cave_sandbox_source_read_grant_escapes_staging
- caveman build: config must use strict lock and required sand
AI-assisted analysis of JuliusBrussee/caveman@766dce6b13 (2026-08-18).
Data as JSON: /api/errors/d1c86549241711cd.
Report an issue: GitHub.