astrid-runtime/astrid · error

private file is not owned by the current user: {}

Error message

private file is not owned by the current user: {}

What it means

Private files must be owned by the current user; the library compares the inode's st_uid to getuid() during validation. If the file exists but belongs to another uid, it refuses to treat it as private, preventing use of state another account could manipulate.

Source

Thrown at crates/astrid-core/src/platform_fs.rs:548

    #[cfg(target_os = "macos")]
    remove_extended_acl_macos(path)?;
    validate_private_file_unix(path)
}

#[cfg(unix)]
fn validate_private_file_unix(path: &Path) -> io::Result<()> {
    use nix::sys::stat::fstat;

    let file = open_file_no_follow_unix(path)?;
    let metadata = fstat(&file).map_err(nix_io_error)?;
    if metadata.st_mode & 0o170_000 != 0o100_000 {
        return Err(io::Error::new(
            io::ErrorKind::InvalidData,
            format!("private path is not a regular file: {}", path.display()),
        ));
    }
    if metadata.st_uid != nix::unistd::getuid().as_raw() {
        return Err(io::Error::new(
            io::ErrorKind::PermissionDenied,
            format!(
                "private file is not owned by the current user: {}",
                path.display()
            ),
        ));
    }
    if metadata.st_mode & 0o777 != 0o600 {
        return Err(io::Error::new(
            io::ErrorKind::PermissionDenied,
            format!("private file is not owner-only: {}", path.display()),
        ));
    }
    if metadata.st_nlink != 1 {
        return Err(io::Error::new(
            io::ErrorKind::InvalidData,
            format!(
                "private file has {} links; durable media must have exactly one",

View on GitHub (pinned to affd8760f4)

Solutions

  1. Chown the file to the current user: `sudo chown $(id -u):$(id -g) <path>`.
  2. Fix the directory ownership recursively: `sudo chown -R $(id -u) <dir>`.
  3. Delete the file and let the library recreate it as the current user (atomic_write_private_file).
  4. Run the application as the user who owns the file, or stop using sudo for it.

Example fix

// before (file owned by root)
validate_private_file(Path::new("/home/me/.astrid/credentials"))?;
// after (fix ownership first)
// $ sudo chown $(id -u):$(id -g) /home/me/.astrid/credentials
validate_private_file(Path::new("/home/me/.astrid/credentials"))?;
Defensive patterns

Strategy: validation

Validate before calling

use std::os::unix::fs::MetadataExt;
fn owned_by_me(path: &std::path::Path) -> bool {
    std::fs::metadata(path).map(|m| m.uid() == unsafe { libc::getuid() }).unwrap_or(false)
}

Type guard

fn is_self_owned(path: &std::path::Path) -> bool {
    std::fs::metadata(path).map(|m| m.uid() == nix::unistd::getuid().as_raw()).unwrap_or(false)
}

Try / catch

match validate_private_file(path) {
    Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied => {
        println!("fix ownership: sudo chown $(id -u) {path:?}");
    },
    other => other?,
}

Prevention

When it happens

Trigger: validate_private_file (or restrict_private_file, which validates at the end) encounters a file whose st_uid differs from the current uid — e.g. created by root, another user, or after a uid change.

Common situations: Files created by running the tool with sudo; a shared/home-directory migration where ownership was not preserved (rsync without -o, tar as another user); container running as a different uid than the volume's file owner; uid remap after LDAP/NSS change.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


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