astrid-runtime/astrid · error
legacy source entry is not owned by the current user: {}
Error message
legacy source entry is not owned by the current user: {} What it means
Under SourceAccess::OwnerControlled, every entry in the legacy source must be owned by the current user (metadata.uid() == getuid()). If any file or directory is owned by another uid, the migration refuses with PermissionDenied to prevent importing files whose owner-controlled semantics you cannot actually enforce.
Source
Thrown at crates/astrid-kernel/src/legacy_migration_barrier/host_fs.rs:777
match access {
SourceAccess::Private => validate_private_entry(path, metadata),
SourceAccess::OwnerControlled => validate_owner_controlled_entry(path, metadata),
}
}
fn validate_owner_controlled_entry(path: &Path, metadata: &fs::Metadata) -> io::Result<()> {
if !metadata.is_dir() && !metadata.is_file() {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("legacy source contains a special entry: {}", path.display()),
));
}
#[cfg(unix)]
{
use std::os::unix::fs::MetadataExt as _;
if metadata.uid() != nix::unistd::getuid().as_raw() {
return Err(io::Error::new(
io::ErrorKind::PermissionDenied,
format!(
"legacy source entry is not owned by the current user: {}",
path.display()
),
));
}
if metadata.mode() & 0o022 != 0 {
return Err(io::Error::new(
io::ErrorKind::PermissionDenied,
format!(
"legacy source entry is group/world writable: {}",
path.display()
),
));
}
astrid_core::platform_fs::validate_no_extended_acl(path)?;
Ok(())View on GitHub (pinned to affd8760f4)
Solutions
- chown the tree to the current user: `sudo chown -R $(id -u):$(id -g) <source>`
- Copy the files with your own user (cp/rsync as yourself) so the copies are owned by you
- Use SourceAccess::Private if a different ownership/permission profile is acceptable
- Run the migration as the user who owns the data
Example fix
// before: entry owned by root, app runs as 'alice' // $ sudo tar -xzf backup.tgz -C /home/alice/data let result = snapshot_path_with_access(path, SourceAccess::OwnerControlled); // Err: legacy source entry is not owned by the current user: ... // after: take ownership before migrating // $ sudo chown -R alice:alice /home/alice/data let result = snapshot_path_with_access(path, SourceAccess::OwnerControlled);
Defensive patterns
Strategy: validation
Validate before calling
#[cfg(unix)]
fn assert_owned_by_current_user(source: &std::path::Path) -> std::io::Result<()> {
use std::os::unix::fs::MetadataExt;
let uid = nix::unistd::getuid().as_raw();
let mut stack = vec![source.to_path_buf()];
while let Some(dir) = stack.pop() {
for entry in std::fs::read_dir(&dir)? {
let path = entry?.path();
let md = std::fs::symlink_metadata(&path)?;
if md.uid() != uid {
return Err(std::io::Error::new(
std::io::ErrorKind::PermissionDenied,
format!("not owned by current user: {}", path.display()),
));
}
if md.is_dir() {
stack.push(path);
}
}
}
Ok(())
} Try / catch
match snapshot_path_with_access(source, SourceAccess::OwnerControlled) {
Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied
&& e.to_string().contains("not owned by the current user") =>
{
eprintln!("fix with: sudo chown -R $(id -u):$(id -g) <source>");
}
other => other?,
} Prevention
- Never unpack archives or copy data into the source with sudo
- Verify with `find <source> ! -user $(whoami)` before migrating
- Run the migration as the same user that owns the data
- Beware NFS root_squash remapping ownership to unexpected uids
When it happens
Trigger: Calling the migration API with SourceAccess::OwnerControlled on a tree containing any entry owned by a different user — e.g. files created by root (via sudo), by another account, or by a container process with a different uid; also files extracted from archives as root.
Common situations: Running the app as a non-root user over data previously written by root; unpacking a tarball with sudo into the source directory; shared directories where a teammate or service account owns some files; NFS rootsquash mapping 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
- legacy source entry is group/world writable: {}
- mountpoint must be owned by the current OS user: {}
- private directory is not owned by the current user: {}
- private file is not owned by the current user: {}
- private file is not owner-only: {}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/4c03a38e67f05301.
Report an issue: GitHub.