astrid-runtime/astrid · error

process write path does not exist: {}

Error message

process write path does not exist: {}

What it means

wrap_with_process_paths validates each extra write path for sandbox interpolation and requires it to exist (io::ErrorKind::NotFound). Write grants in the sandbox profile must correspond to real locations, so a missing path is rejected instead of producing an ineffective grant.

Source

Thrown at crates/astrid-workspace/src/sandbox/mod.rs:275

        // but we still reject unsafe paths at the API boundary.
        let _ = validate_sandbox_str(worktree_path, "worktree path")?;
        for inj in injections {
            let _ = validate_sandbox_str(&inj.source, "injection source")?;
            let _ = validate_sandbox_str(&inj.target, "injection target")?;
        }
        for path in extra_read_paths {
            let _ = validate_sandbox_str(path, "process read path")?;
            if !path.exists() {
                return Err(io::Error::new(
                    io::ErrorKind::NotFound,
                    format!("process read path does not exist: {}", path.display()),
                ));
            }
        }
        for path in extra_write_paths {
            let _ = validate_sandbox_str(path, "process write path")?;
            if !path.exists() {
                return Err(io::Error::new(
                    io::ErrorKind::NotFound,
                    format!("process write path does not exist: {}", path.display()),
                ));
            }
        }

        // Every caller-supplied mask names copy-on-write bookkeeping the child
        // must not reach (the overlayfs upper/work, or the APFS pristine). Each is
        // validated exactly like the worktree and injection paths — absolute,
        // UTF-8, SBPL-safe — because on macOS it is interpolated into the Seatbelt
        // profile; then it must EXIST, since a path that does not exist is a wiring
        // bug, not a no-op (silently skipping it leaves the child un-denied). The
        // deny is security-critical, so either failure fails the spawn closed.
        for masked in extra_masks {
            let _ = validate_sandbox_str(masked, "workspace CoW mask")?;
            if !masked.exists() {
                return Err(io::Error::new(
                    io::ErrorKind::NotFound,

View on GitHub (pinned to affd8760f4)

Solutions

  1. Pre-create the path with fs::create_dir_all(path) before calling wrap_with_process_paths
  2. For files, create the parent directory and touch the file if the grant targets a file
  3. Filter or canonicalize the write paths first, handling missing ones explicitly
  4. Correct the configured path so it matches an existing location

Example fix

// before
wrap_with_process_paths(&ws, &[], &[PathBuf::from("/tmp/myapp/out")])?;
// after
let out = PathBuf::from("/tmp/myapp/out");
std::fs::create_dir_all(&out)?;
wrap_with_process_paths(&ws, &[], &[out])?;
Defensive patterns

Strategy: validation

Validate before calling

for p in write_paths { if !p.exists() { std::fs::create_dir_all(p)?; } }

Type guard

fn writable_target_exists(p: &Path) -> bool { p.exists() }

Try / catch

match wrap_with_process_paths(&ws, &[], &write_paths) { Err(e) if e.kind() == io::ErrorKind::NotFound => { /* create_dir_all the reported path and retry once */ }, other => other, }

Prevention

When it happens

Trigger: Calling the public wrap_with_process_paths with an extra_write_paths entry that is a valid absolute UTF-8 path but does not exist on disk — e.g. an output directory not yet created, or a path deleted after configuration was written.

Common situations: Output/build directories that the tool expects the caller to pre-create; paths on a mounted volume not yet mounted; typo'd absolute paths in config; CI environments missing a directory created by an earlier step.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/0ab38ec1ec20cf07. Report an issue: GitHub.