Hmbown/CodeWhale · error
deliverable is outside the worker write scope; declare an…
Error message
deliverable {path:?} is outside the worker write scope; declare an exact_files entry or a containing write_roots path What it means
Each declared deliverable path must fall inside the worker's write scope. If the agent is write-capable, the spawn validates every deliverable against its write_claim (exact_files or write_roots); a deliverable that is neither covered by an exact_files entry nor contained in a write_roots path is rejected. This prevents workers from being asked to produce files they are not authorized to write.
Solutions
- Add the deliverable's exact path to the write_claim's exact_files list.
- Or add/extend a write_roots entry so it contains (is a parent directory of) the deliverable path.
- Verify path forms match: both the deliverable and the claim must resolve against the same workspace root; fix absolute-vs-relative mismatches.
Example fix
// before
write_claim: WriteClaim { write_roots: vec!["src/".into()], exact_files: vec![] },
deliverables: vec!["src/report.md".into(), "tests/report_test.rs".into()]
// after
write_claim: WriteClaim {
write_roots: vec!["src/".into()],
exact_files: vec!["tests/report_test.rs".into()],
},
deliverables: vec!["src/report.md".into(), "tests/report_test.rs".into()] Defensive patterns
Strategy: validation
Validate before calling
function deliverablesInScope(deliverables, claim) {
return deliverables.every(p =>
claim.exactFiles.includes(p) || claim.writeRoots.some(root => p.startsWith(root)));
} Type guard
const isCovered = (p, claim) =>
claim.exact_files.includes(p) || claim.write_roots.some(r => p === r || p.startsWith(r.trim_end_matches('/') + '/')); Try / catch
match spawn_result {
Err(e) if e.to_string().contains("outside the worker write scope") => fix_write_claim_and_retry(),
other => other?,
} Prevention
- Derive the deliverables list from the write claim (or vice versa) in one place, never maintained separately.
- Normalize path forms (workspace-relative) for both deliverables and write_roots.
- When adding a deliverable, immediately extend exact_files or a write_root.
When it happens
Trigger: Spawning a write-capable sub-agent whose `deliverables` list includes a path outside the paths granted by options.write_claim (write_claim.contains_path returns false for it, or write_claim is None).
Common situations: Deliverables declared as bare file names or absolute paths while write_roots use relative workspace paths; adding a new deliverable after tightening the write claim; forgetting to declare the deliverable in exact_files at all.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- agent action=claim widens an enforced write scope, and the…
- Checkpoint continuation requires a source agent
- Custom sub-agent requires a non-empty allowed_tools list
- Fleet authority fingerprint
- sub-agent state path must be a regular file
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/9baecfbc0b99890d.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tools/subagent/mod.rs:7089
let delivery_paths =
delivery::declared_paths(&options.deliverables, options.expected_artifact.as_deref())
.map_err(anyhow::Error::msg)?;
for path in &delivery_paths {
delivery::safe_deliverable_path(&agent.workspace, path).map_err(anyhow::Error::msg)?;
let claimed_path = if options.claim_pre_namespaced && !options.isolated_worktree {
let prefix = coordination_workspace_prefix(&self.workspace, &agent.workspace)
.map_err(anyhow::Error::msg)?;
namespace_coordination_path(&prefix, path).map_err(anyhow::Error::msg)?
} else {
path.clone()
};
if !write_capable
|| !options
.write_claim
.as_ref()
.is_some_and(|claim| claim.contains_path(&claimed_path))
{
return Err(anyhow!(
"deliverable {path:?} is outside the worker write scope; declare an exact_files entry or a containing write_roots path"
));
}
}
if write_capable {
// Isolated-worktree children mutate their own checkout, so they
// do not contend for the shared-workspace process lock (#5036).
if !options.isolated_worktree {
self.ensure_coordination_process_lock()
.map_err(anyhow::Error::msg)?;
}
if self.coordination_process_lock_required && self.state_path.is_none() {
return Err(anyhow!(
"write-capable sub-agent launch requires a durable coordination state path"
));
}
}
let durable_registration = write_capable || continuation_from.is_some();View on GitHub (pinned to 73e0f67d83)