zed-industries/zed · error
cannot capture writable sandbox path `{}`
Error message
cannot capture writable sandbox path `{}` What it means
When building the sandbox fs policy (allow_fs_write == false), every worktree path in writable_paths is re-captured via sandbox::HostFilesystemLocation::capture; a capture failure wraps the error with this context and fails the whole terminal construction. The design is fail-closed: a writable path that cannot be captured is never silently dropped from the sandbox.
Source
Thrown at crates/acp_thread/src/terminal.rs:279
/// synthesized `settings.json/.git` routes through a file — without closing
/// the hole. So we drop and move on.
fn to_policy(&self) -> Result<sandbox::SandboxPolicy> {
let protected_paths = self
.protected_paths
.iter()
.filter_map(|path| sandbox::HostFilesystemLocation::capture(path).ok())
.collect::<Vec<_>>();
let fs = if self.allow_fs_write {
sandbox::SandboxFsPolicy::Unrestricted { protected_paths }
} else {
// Project worktree paths are captured fresh; user-approved grants are
// rebuilt via the verifying reopen (or captured when legacy bare
// strings) through `granted_write_path_to_location`. A path that
// can't be captured fails the whole construction (never created).
let mut locations = Vec::new();
for path in &self.writable_paths {
let location = sandbox::HostFilesystemLocation::capture(path).map_err(|error| {
anyhow::anyhow!(error).context(format!(
"cannot capture writable sandbox path `{}`",
path.display()
))
})?;
locations.push(location);
}
for granted in &self.extra_write_paths {
let location = granted_write_path_to_location(granted).map_err(|error| {
anyhow::anyhow!(error).context(format!(
"cannot re-verify approved sandbox write grant `{}` (if the \
directory was removed, remove the grant or recreate the \
directory)",
granted.requested.display()
))
})?;
locations.push(location);
}
// Dedupe to a minimal cover on the captured canonical paths, so aView on GitHub (pinned to bc538def45)
Solutions
- Recreate the missing directory named in the error, or re-open the project so the worktree list refreshes
- Remove the stale worktree from the project before spawning further agent terminals
- Fix directory permissions if the path exists but cannot be captured
Defensive patterns
Strategy: validation
Validate before calling
// Verify every writable path still exists before spawning the terminal
let missing: Vec<_> = writable_paths.iter()
.filter(|path| !path.exists())
.cloned()
.collect();
if !missing.is_empty() {
return notify_user(format!("worktree paths no longer exist: {missing:?}"));
} Type guard
fn all_writable_paths_exist(paths: &[Arc<Path>]) -> bool {
paths.iter().all(|path| path.is_dir())
} Prevention
- Re-validate worktree paths when the project regains focus; stale lists are the usual cause
- Remove deleted worktrees from the project instead of leaving them registered
- Surface the exact path from the error message — it names the offender
When it happens
Trigger: A directory listed in writable_paths no longer exists (deleted, renamed, unmounted) or is unreadable at terminal-spawn time — e.g. the worktree was removed externally while the project stayed open.
Common situations: User deletes a multiworktree folder with the agent panel open; git prunes a worktree; permissions on the directory changed; a removable/FUSE mount holding the worktree went away.
Related errors
- cannot re-verify approved sandbox write grant `{}` (if the d
- Terminal with id `{}` not found
- Unexpected response structure: ${JSON.stringify(data)}
- not implemented
- output token limit reached
AI-assisted analysis of zed-industries/zed@bc538def45 (2026-08-16).
Data as JSON: /api/errors/2b4043b02de1ca62.
Report an issue: GitHub.