astrid-runtime/astrid · error
private directory is not owner-only: {}
Error message
private directory is not owner-only: {} What it means
validate_private_directory_unix requires the directory's permission mode to be exactly 0700 (owner read/write/execute, nothing for group or other). Any looser mode (e.g. 0755 or 0770) widens access beyond the owner and fails with io::ErrorKind::PermissionDenied. Extended ACLs are checked separately afterwards.
Source
Thrown at crates/astrid-core/src/platform_fs.rs:506
}
#[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)]
fn restrict_private_file_unix(path: &Path) -> io::Result<()> {
use nix::sys::stat::{Mode, fchmod, 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()),View on GitHub (pinned to affd8760f4)
Solutions
- chmod 700 the directory (and any nested real directories), or call ensure_private_directory / ensure_private_directory_tree which repairs modes automatically.
- Remove the permissive directory and let the library recreate it with 0700.
- Check for tools (backups, sync clients) that rewrite permissions and re-run validation after they run.
Example fix
// before (shell)
ls -ld ~/.astrid // drwxr-xr-x
// after (shell)
chmod 700 ~/.astrid
// or in Rust: let the library repair it
ensure_private_directory_tree(&home.join(".astrid"))?; Defensive patterns
Strategy: validation
Validate before calling
#[cfg(unix)]
fn is_owner_only(p: &std::path::Path) -> std::io::Result<bool> {
use std::os::unix::fs::PermissionsExt;
Ok(std::fs::metadata(p)?.permissions().mode() & 0o777 == 0o700)
} Type guard
#[cfg(unix)]
fn has_0700(p: &std::path::Path) -> bool {
use std::os::unix::fs::PermissionsExt;
std::fs::metadata(p)
.map(|m| m.permissions().mode() & 0o777 == 0o700)
.unwrap_or(false)
} Try / catch
match validate_private_directory(&dir) {
Err(e) if e.kind() == io::ErrorKind::PermissionDenied && e.to_string().contains("owner-only") => {
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
std::fs::set_permissions(&dir, std::fs::Permissions::from_mode(0o700))?;
}
}
other => other?,
} Prevention
- Set a restrictive umask (077) for processes that create private state
- Call ensure_private_directory/ensure_private_directory_tree to repair modes automatically
- Audit for tools (sync/backup clients) that loosen permissions on the private tree
When it happens
Trigger: Calling validate_private_directory or ensure_private_directory_unix on an existing directory whose mode & 0o777 != 0o700 — typically a 0755 layout-1 leftover or a umask-loosened mkdir.
Common situations: Older Astrid layouts (0755 COW slots/unpacked homes) after upgrade; restores that lost the 0700 bit; processes with permissive umask creating the directory first.
Understand the failure class
Background: "You do not have permission" / 403 Forbidden errors: authenticated but not allowed — causes and fixes across open-source libraries — this error's family across 31 libraries.
Related errors
- private directory is not owned by the current user: {}
- mountpoint ancestor is writable without sticky protection: {
- inspect legacy revocation file: {error}
- read materialized capsule metadata: {error:#}
- read materialized capsule authority: {error:#}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/568e5c387b6be527.
Report an issue: GitHub.