JuliusBrussee/caveman · error
cave_sandbox_side_effect_denied
cave_sandbox_side_effect_denied
Error message
cave_sandbox_side_effect_denied
What it means
The sandbox executes the selected tool only if its declared effect is "read", or the request explicitly set allowSideEffects to true. Any tool with effect "write" (or another non-read effect) under allowSideEffects !== true is refused before execute — this is the sandbox's side-effect containment guarantee.
Source
Thrown at packages/agent/src/tool-worker.ts:134
if (delegated.length !== 1) throw new Error("cave_sandbox_unknown_subagent");
const child = delegated[0]!.runtime!.definition as AgentDefinition;
if (!child || child.kind !== "agent") {
throw new Error("cave_sandbox_subagent_definition_invalid");
}
if (visited.has(child)) throw new Error("cave_sandbox_subagent_cycle");
visited.add(child);
definition = child;
}
const selectedTools = definition.tools.filter((item) => item.name === request.tool);
if (selectedTools.length !== 1 || selectedTools[0]!.runtime?.kind === "subagent") {
throw new Error("cave_sandbox_unknown_tool");
}
const selected = selectedTools[0]!;
if (toolDefinitionSHA256(selected) !== request.toolDefinitionSha256) {
throw new Error("cave_sandbox_tool_definition_mismatch");
}
if (selected.effect !== "read" && request.allowSideEffects !== true) {
throw new Error("cave_sandbox_side_effect_denied");
}
const value = await selected.execute(request.params as never, AbortSignal.timeout(selected.timeoutMs));
writeResult({ ok: true, value });
} catch (error) {
writeResult({ ok: false, code: failureCode(error) });
}
View on GitHub (pinned to 27d5a3981a)
Solutions
- If the mutation is intended, spawn the worker request with allowSideEffects: true (and understand the sandbox then permits writes).
- If the tool is genuinely read-only, correct its declaration to effect:"read".
- Route unintended write attempts to a read-only equivalent tool in the parent's admission logic.
Example fix
// before
{ tool: "write_file", params: {...}, allowSideEffects: false }
// after
effect === "read"
? { tool: "write_file", params: {...} }
: { tool: "write_file", params: {...}, allowSideEffects: true } Defensive patterns
Strategy: validation
Validate before calling
const needsSideEffects = selected.effect !== "read";
if (needsSideEffects && request.allowSideEffects !== true) {
throw new Error(`tool ${selected.name} declares effect=${selected.effect}; require explicit operator approval`);
} Type guard
function isReadOnlyTool(t: { effect?: string }): boolean {
return t.effect === "read";
} Prevention
- Declare effect accurately on every tool.
- Gate allowSideEffects:true behind explicit operator consent in your admission layer.
- Default runs to read-only; treat this error as the sandbox working, not a bug.
When it happens
Trigger: Calling a tool whose definition declares effect:"write" (or "side_effect") while the spawning request was built with allowSideEffects:false or omitted it; a run in read-only/observe mode attempting a mutating tool.
Common situations: Default sandbox policy is read-only and the developer forgot to opt into side effects for this run; a tool was misdeclared as write when it is actually read-only; CI runs pinned to allowSideEffects:false hitting a write tool.
Related errors
- cave_host_sandbox_nested_under_required
- cave_sandbox_agent_export_missing
- cave_sandbox_definition_mismatch
- cave_sandbox_unknown_subagent
- cave_sandbox_subagent_definition_invalid
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/04b6f85efee55f31.
Report an issue: GitHub.