{"record":{"id":"0ab38ec1ec20cf07","repo":"astrid-runtime/astrid","slug":"process-write-path-does-not-exist","errorCode":null,"errorMessage":"process write path does not exist: {}","messagePattern":"process write path does not exist: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-workspace/src/sandbox/mod.rs","lineNumber":275,"sourceCode":"        // but we still reject unsafe paths at the API boundary.\n        let _ = validate_sandbox_str(worktree_path, \"worktree path\")?;\n        for inj in injections {\n            let _ = validate_sandbox_str(&inj.source, \"injection source\")?;\n            let _ = validate_sandbox_str(&inj.target, \"injection target\")?;\n        }\n        for path in extra_read_paths {\n            let _ = validate_sandbox_str(path, \"process read path\")?;\n            if !path.exists() {\n                return Err(io::Error::new(\n                    io::ErrorKind::NotFound,\n                    format!(\"process read path does not exist: {}\", path.display()),\n                ));\n            }\n        }\n        for path in extra_write_paths {\n            let _ = validate_sandbox_str(path, \"process write path\")?;\n            if !path.exists() {\n                return Err(io::Error::new(\n                    io::ErrorKind::NotFound,\n                    format!(\"process write path does not exist: {}\", path.display()),\n                ));\n            }\n        }\n\n        // Every caller-supplied mask names copy-on-write bookkeeping the child\n        // must not reach (the overlayfs upper/work, or the APFS pristine). Each is\n        // validated exactly like the worktree and injection paths — absolute,\n        // UTF-8, SBPL-safe — because on macOS it is interpolated into the Seatbelt\n        // profile; then it must EXIST, since a path that does not exist is a wiring\n        // bug, not a no-op (silently skipping it leaves the child un-denied). The\n        // deny is security-critical, so either failure fails the spawn closed.\n        for masked in extra_masks {\n            let _ = validate_sandbox_str(masked, \"workspace CoW mask\")?;\n            if !masked.exists() {\n                return Err(io::Error::new(\n                    io::ErrorKind::NotFound,","sourceCodeStart":257,"sourceCodeEnd":293,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-workspace/src/sandbox/mod.rs#L257-L293","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pre-create the path with fs::create_dir_all(path) before calling wrap_with_process_paths","For files, create the parent directory and touch the file if the grant targets a file","Filter or canonicalize the write paths first, handling missing ones explicitly","Correct the configured path so it matches an existing location"],"exampleFix":"// before\nwrap_with_process_paths(&ws, &[], &[PathBuf::from(\"/tmp/myapp/out\")])?;\n// after\nlet out = PathBuf::from(\"/tmp/myapp/out\");\nstd::fs::create_dir_all(&out)?;\nwrap_with_process_paths(&ws, &[], &[out])?;","handlingStrategy":"validation","validationCode":"for p in write_paths { if !p.exists() { std::fs::create_dir_all(p)?; } }","typeGuard":"fn writable_target_exists(p: &Path) -> bool { p.exists() }","tryCatchPattern":"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, }","preventionTips":["Create output directories before configuring the sandbox","Validate write targets at pipeline start, before any long-running setup","Ensure mounted volumes are attached before the sandbox profile is built"],"tags":["sandbox","path","file-not-found","validation"],"backgroundTag":"file-not-found","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}