{"record":{"id":"5e2f3927d11f9193","repo":"astrid-runtime/astrid","slug":"private-path-is-not-a-regular-file","errorCode":null,"errorMessage":"private path is not a regular file: {}","messagePattern":"private path is not a regular file: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-core/src/platform_fs.rs","lineNumber":522,"sourceCode":"    }\n    if metadata.permissions().mode() & 0o777 != 0o700 {\n        return Err(io::Error::new(\n            io::ErrorKind::PermissionDenied,\n            format!(\"private directory is not owner-only: {}\", path.display()),\n        ));\n    }\n    validate_no_extended_acl(path)?;\n    Ok(())\n}\n\n#[cfg(unix)]\nfn restrict_private_file_unix(path: &Path) -> io::Result<()> {\n    use nix::sys::stat::{Mode, fchmod, fstat};\n\n    let file = open_file_no_follow_unix(path)?;\n    let metadata = fstat(&file).map_err(nix_io_error)?;\n    if metadata.st_mode & 0o170_000 != 0o100_000 {\n        return Err(io::Error::new(\n            io::ErrorKind::InvalidData,\n            format!(\"private path is not a regular file: {}\", path.display()),\n        ));\n    }\n    fchmod(&file, Mode::from_bits_truncate(0o600)).map_err(nix_io_error)?;\n    file.sync_all()?;\n    drop(file);\n    #[cfg(target_os = \"macos\")]\n    remove_extended_acl_macos(path)?;\n    validate_private_file_unix(path)\n}\n\n#[cfg(unix)]\nfn validate_private_file_unix(path: &Path) -> io::Result<()> {\n    use nix::sys::stat::fstat;\n\n    let file = open_file_no_follow_unix(path)?;\n    let metadata = fstat(&file).map_err(nix_io_error)?;","sourceCodeStart":504,"sourceCodeEnd":540,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-core/src/platform_fs.rs#L504-L540","documentation":"Astrid enforces that private security-sensitive paths are regular files before restricting their permissions to 0600. This error is thrown by restrict_private_file_unix when fstat on the no-follow-opened path shows the file type bits are not S_IFREG (0o100000), e.g. the path is a directory, device, FIFO, socket, or symlink target of that kind. It is a defensive check so ownership/permission hardening is never applied to non-regular inodes.","triggerScenarios":"Calling restrict_private_file (or an API that uses it) with a path that resolves to a directory, character/block device, FIFO, socket, or other non-regular inode. Because the file is opened with O_NOFOLLOW, the fstat reflects the real target of the final component.","commonSituations":"Pointing a private-file config option at a directory instead of a file; a FIFO or socket exists at the expected path; a leftover mount point or /dev-style device file sits where a token/credential file should be.","solutions":["Point the API at an actual regular file path, not a directory or special file.","If a directory exists at that path, move or rename it and let the library create the file.","Check the path with `stat -c '%F' <path>` (or `ls -l`) to confirm it is a regular file before retrying.","If a device/FIFO was intentionally placed there, remove it; private state must live in a regular file."],"exampleFix":"// before\nrestrict_private_file(Path::new(\"/home/me/.astrid\"))?; // directory\n// after\nrestrict_private_file(Path::new(\"/home/me/.astrid/credentials\"))?; // regular file","handlingStrategy":"validation","validationCode":"use std::os::unix::fs::FileTypeExt;\nfn is_regular_file(path: &std::path::Path) -> std::io::Result<bool> {\n    Ok(std::fs::symlink_metadata(path)?.file_type().is_file())\n}\nif !is_regular_file(path)? { return Err(anyhow!(\"{} must be a regular file\", path.display())); }","typeGuard":"fn is_regular(path: &std::path::Path) -> bool {\n    std::fs::symlink_metadata(path).map(|m| m.is_file()).unwrap_or(false)\n}","tryCatchPattern":"match restrict_private_file(path) {\n    Err(e) if e.kind() == std::io::ErrorKind::InvalidData => eprintln!(\"not a regular file: {e}\"),\n    other => other?,\n}","preventionTips":["Point private-path config at concrete file paths, never directories","Check `stat -c '%F'` on the path before wiring it up","Do not place FIFOs/sockets in private state directories"],"tags":["filesystem","unix","permission-denied","path-validation"],"backgroundTag":"path-is-not-a-directory","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"}