astrid-runtime/astrid · error
private directory is not owned by the current user: {}
Error message
private directory is not owned by the current user: {} What it means
validate_private_directory_unix requires the private directory to be owned by the current user's uid. Ownership by another user means another account (or root) controls the directory contents, breaking the per-user privacy contract, so it fails with io::ErrorKind::PermissionDenied.
Source
Thrown at crates/astrid-core/src/platform_fs.rs:497
},
Err(error) => return Err(nix_io_error(error)),
};
directory = std::fs::File::from(next);
}
fchmod(&directory, Mode::from_bits_truncate(0o700)).map_err(nix_io_error)?;
#[cfg(target_os = "macos")]
remove_extended_acl_macos(path)?;
validate_private_directory_unix(path)
}
#[cfg(unix)]
fn validate_private_directory_unix(path: &Path) -> io::Result<()> {
use std::os::unix::fs::{MetadataExt as _, PermissionsExt as _};
let directory = open_directory_no_follow_unix(path)?;
let metadata = directory.metadata()?;
if metadata.uid() != nix::unistd::getuid().as_raw() {
return Err(io::Error::new(
io::ErrorKind::PermissionDenied,
format!(
"private directory is not owned by the current user: {}",
path.display()
),
));
}
if metadata.permissions().mode() & 0o777 != 0o700 {
return Err(io::Error::new(
io::ErrorKind::PermissionDenied,
format!("private directory is not owner-only: {}", path.display()),
));
}
validate_no_extended_acl(path)?;
Ok(())
}
#[cfg(unix)]View on GitHub (pinned to affd8760f4)
Solutions
- Reclaim ownership: chown -R $(id -u) ~/.astrid (run as the owner or with sudo).
- Avoid creating the directory with sudo; let the target user's process create it.
- If a foreign-owned directory is unexpected, remove it and let ensure_private_directory recreate it securely.
Example fix
// before (shell) sudo mkdir ~/.astrid // after (shell) rm -rf ~/.astrid && mkdir ~/.astrid && chmod 700 ~/.astrid // owned by current user
Defensive patterns
Strategy: validation
Validate before calling
#[cfg(unix)]
fn owned_by_me(p: &std::path::Path) -> std::io::Result<bool> {
use std::os::unix::fs::MetadataExt;
Ok(std::fs::metadata(p)?.uid() == nix::unistd::getuid().as_raw())
} Type guard
#[cfg(unix)]
fn current_user_owns(p: &std::path::Path) -> bool {
use std::os::unix::fs::MetadataExt;
std::fs::symlink_metadata(p)
.map(|m| m.uid() == nix::unistd::getuid().as_raw())
.unwrap_or(false)
} Try / catch
match validate_private_directory(&dir) {
Err(e) if e.kind() == io::ErrorKind::PermissionDenied => {
eprintln!("run 'chown -R $(id -u) {}' or recreate the directory", dir.display());
return Err(e);
}
other => other?,
} Prevention
- Never create private state directories with sudo
- Fix ownership after rsync/tar restores
- Check directory uid once at startup with a clear remediation message
When it happens
Trigger: Calling validate_private_directory or ensure_private_directory_unix on a directory whose stat uid differs from getuid() — e.g. a directory created by sudo, restored from another user's backup, or on a shared/multi-user mount.
Common situations: Running the app under a different account after creating state with sudo; rsync/tar restores that preserved foreign ownership; shared /home or NFS directories with mixed uids.
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
- private directory is not owner-only: {}
- mountpoint ancestor is writable without sticky protection: {
- mountpoint must be owned by the current OS user: {}
- inspect legacy revocation file: {error}
- read materialized capsule metadata: {error:#}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/90668ab3eeb95aa1.
Report an issue: GitHub.