astrid-runtime/astrid · error

private file is not owner-only: {}

Error message

private file is not owner-only: {}

What it means

A private file must have mode exactly 0600 (owner read/write, no group/other bits). The library throws this when validation finds st_mode & 0o777 != 0o600, because looser permissions would expose security-sensitive content to other local users.

Source

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

    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",
                metadata.st_nlink
            ),
        ));
    }
    validate_no_extended_acl(path)?;
    Ok(())
}

#[cfg(target_os = "macos")]

View on GitHub (pinned to affd8760f4)

Solutions

  1. Chmod the file to owner-only: `chmod 600 <path>`.
  2. Call the library's restrict_private_file, which fchmods the file to 0600 and revalidates.
  3. Delete and recreate the file through the library so it is created with 0600.
  4. Ensure any external tooling that rewrites the file also sets 0600 (set umask 077 or explicit chmod in scripts).

Example fix

// before (file has 0644)
validate_private_file(Path::new("/home/me/.astrid/credentials"))?;
// after (fix mode first)
// $ chmod 600 /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::PermissionsExt;
fn mode_is_600(path: &std::path::Path) -> bool {
    std::fs::metadata(path).map(|m| m.permissions().mode() & 0o777 == 0o600).unwrap_or(false)
}

Type guard

fn is_owner_only(path: &std::path::Path) -> bool {
    std::fs::metadata(path)
        .map(|m| m.permissions().mode() & 0o777 == 0o600)
        .unwrap_or(false)
}

Try / catch

if let Err(e) = validate_private_file(path) {
    if e.kind() == std::io::ErrorKind::PermissionDenied {
        std::fs::set_permissions(path, std::fs::Permissions::from_mode(0o600))?;
    } else { return Err(e.into()); }
}

Prevention

When it happens

Trigger: validate_private_file sees a file with e.g. 0644, 0664, or 0666 permissions. Happens when the file was created outside the library, copied with permissions preserved, or had permissions loosened after creation.

Common situations: rsync/scp/tar copies preserving 0644; a umask of 0022 applied when another tool created the file; editor or backup tool rewrote the file with default perms; restoring from a backup with relaxed modes.

Understand the failure class

Background: "Permission denied" / "Failed to write" file errors: why a library can't write its files to disk (EACCES, EPERM, ENOSPC) and how to fix them — this error's family across 43 libraries.

Related errors


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