{"record":{"id":"dc9aedf322ec785b","repo":"astrid-runtime/astrid","slug":"private-path-has-no-parent","errorCode":null,"errorMessage":"private path has no parent: {}","messagePattern":"private path has no parent: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-core/src/platform_fs.rs","lineNumber":432,"sourceCode":"        let _ = path;\n        Ok(())\n    }\n}\n\n#[cfg(unix)]\nfn verify_no_redirects_unix(path: &Path) -> io::Result<()> {\n    use nix::fcntl::{OFlag, openat};\n    use nix::sys::stat::Mode;\n\n    match std::fs::symlink_metadata(path) {\n        Ok(metadata) if metadata.file_type().is_symlink() => Err(io::Error::new(\n            io::ErrorKind::InvalidData,\n            format!(\"private path is redirected: {}\", path.display()),\n        )),\n        Ok(metadata) if metadata.is_dir() => open_directory_no_follow_unix(path).map(drop),\n        Ok(_) => {\n            let parent = path.parent().ok_or_else(|| {\n                io::Error::new(\n                    io::ErrorKind::InvalidInput,\n                    format!(\"private path has no parent: {}\", path.display()),\n                )\n            })?;\n            let name = path.file_name().ok_or_else(|| {\n                io::Error::new(\n                    io::ErrorKind::InvalidInput,\n                    format!(\"private path has no file name: {}\", path.display()),\n                )\n            })?;\n            let directory = open_directory_no_follow_unix(parent)?;\n            let flags = OFlag::O_RDONLY | OFlag::O_NOFOLLOW | OFlag::O_CLOEXEC | OFlag::O_NONBLOCK;\n            openat(&directory, name, flags, Mode::empty())\n                .map(std::fs::File::from)\n                .map(drop)\n                .map_err(nix_io_error)\n        },\n        Err(error) if error.kind() == io::ErrorKind::NotFound => {","sourceCodeStart":414,"sourceCodeEnd":450,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-core/src/platform_fs.rs#L414-L450","documentation":"While verifying that a private path is not redirected, verify_no_redirects_unix needs the parent directory to open it no-follow. If path.parent() returns None (a bare root or malformed path), it fails with io::ErrorKind::InvalidInput.","triggerScenarios":"Calling verify_no_redirects with a path such as \"/\" or an empty/oddly formed Path whose parent cannot be determined.","commonSituations":"Misconfigured root path in config (e.g. private dir set to \"/\"); programmatic path built by repeatedly calling .parent() until None; a bug constructing paths from empty strings.","solutions":["Pass a concrete nested path (e.g. $HOME/.astrid) rather than a filesystem root.","Validate the configured path has a parent before calling: path.parent().is_some().","Fix path construction so it never degenerates to the root or empty path."],"exampleFix":"// before\nlet target: &Path = cfg.private_dir.as_ref();\nverify_no_redirects(target)?;\n// after\nlet target: &Path = cfg.private_dir.as_ref();\nassert!(target.parent().is_some(), \"private path must not be a filesystem root\");\nverify_no_redirects(target)?;","handlingStrategy":"validation","validationCode":"if path.parent().is_none() {\n    return Err(\"private path must not be a filesystem root\".into());\n}","typeGuard":"fn has_parent(p: &std::path::Path) -> bool { p.parent().is_some() }","tryCatchPattern":"match verify_no_redirects(&path) {\n    Err(e) if e.kind() == io::ErrorKind::InvalidInput => eprintln!(\"path must be nested, not a root: {e}\"),\n    other => other?,\n}","preventionTips":["Reject filesystem roots in user-supplied config for private paths","Construct private paths from an anchored home directory, never bare roots","Validate config paths at startup before touching the filesystem"],"tags":["io","filesystem","invalid-path"],"backgroundTag":"invalid-argument-value","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}