{"record":{"id":"0016deb46e0bf8bd","repo":"astrid-runtime/astrid","slug":"process-read-path-does-not-exist","errorCode":null,"errorMessage":"process read path does not exist: {}","messagePattern":"process read path does not exist: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-workspace/src/sandbox/mod.rs","lineNumber":266,"sourceCode":"        injections: &[RoInjection],\n        extra_masks: &[PathBuf],\n        extra_read_paths: &[PathBuf],\n        extra_write_paths: &[PathBuf],\n        clear_env: bool,\n    ) -> io::Result<Command> {\n        // Validate on all platforms for defense in depth and API consistency.\n        // On macOS the validated string is needed for SBPL interpolation.\n        // On Linux bwrap passes paths as argv entries (no injection risk),\n        // 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,","sourceCodeStart":248,"sourceCodeEnd":284,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-workspace/src/sandbox/mod.rs#L248-L284","documentation":"wrap_with_process_paths validates each extra read path for sandbox interpolation and additionally requires it to exist on disk (io::ErrorKind::NotFound). Extra read paths are granted read access in the sandbox profile, and a nonexistent grant is treated as a configuration error rather than silently ignored.","triggerScenarios":"Calling the public wrap_with_process_paths with an extra_read_paths entry that passes validate_sandbox_str (absolute, UTF-8, no forbidden chars) but does not exist at call time — e.g. a stale cache directory, a deleted temp dir, or a typo'd absolute path.","commonSituations":"Config referencing directories removed between runs; macOS Seatbelt grants for paths like ~/Library/Caches that were cleared; absolute paths typed by hand with a typo; containers where the host path is absent.","solutions":["Create the directory before calling: fs::create_dir_all(path)","Call fs::canonicalize first and skip/report paths that fail","Filter extra_read_paths to those with path.exists() when absence is acceptable","Fix the configuration/typo so the path points to an existing location"],"exampleFix":"// before\nwrap_with_process_paths(&ws, &[PathBuf::from(\"/var/cache/myapp\")], &[])?;\n// after\nlet p = PathBuf::from(\"/var/cache/myapp\");\nstd::fs::create_dir_all(&p)?;\nwrap_with_process_paths(&ws, &[p], &[])?;","handlingStrategy":"validation","validationCode":"for p in read_paths { if !p.exists() { return Err(io::Error::new(io::ErrorKind::NotFound, format!(\"missing read path: {}\", p.display()))); } }","typeGuard":"fn exists(p: &Path) -> bool { p.exists() }","tryCatchPattern":"match wrap_with_process_paths(&ws, &read_paths, &[]) { Err(e) if e.kind() == io::ErrorKind::NotFound => { /* create the directory or drop the path, then retry */ }, other => other, }","preventionTips":["Pre-create all extra read directories with fs::create_dir_all before wrapping a process","Re-check path existence at startup, not just at configuration load","Treat existence checks as part of environment setup in CI/containers"],"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"}