{"record":{"id":"4c03a38e67f05301","repo":"astrid-runtime/astrid","slug":"legacy-source-entry-is-not-owned-by-the-current-us","errorCode":null,"errorMessage":"legacy source entry is not owned by the current user: {}","messagePattern":"legacy source entry is not owned by the current user: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-kernel/src/legacy_migration_barrier/host_fs.rs","lineNumber":777,"sourceCode":"    match access {\n        SourceAccess::Private => validate_private_entry(path, metadata),\n        SourceAccess::OwnerControlled => validate_owner_controlled_entry(path, metadata),\n    }\n}\n\nfn validate_owner_controlled_entry(path: &Path, metadata: &fs::Metadata) -> io::Result<()> {\n    if !metadata.is_dir() && !metadata.is_file() {\n        return Err(io::Error::new(\n            io::ErrorKind::InvalidData,\n            format!(\"legacy source contains a special entry: {}\", path.display()),\n        ));\n    }\n    #[cfg(unix)]\n    {\n        use std::os::unix::fs::MetadataExt as _;\n\n        if metadata.uid() != nix::unistd::getuid().as_raw() {\n            return Err(io::Error::new(\n                io::ErrorKind::PermissionDenied,\n                format!(\n                    \"legacy source entry is not owned by the current user: {}\",\n                    path.display()\n                ),\n            ));\n        }\n        if metadata.mode() & 0o022 != 0 {\n            return Err(io::Error::new(\n                io::ErrorKind::PermissionDenied,\n                format!(\n                    \"legacy source entry is group/world writable: {}\",\n                    path.display()\n                ),\n            ));\n        }\n        astrid_core::platform_fs::validate_no_extended_acl(path)?;\n        Ok(())","sourceCodeStart":759,"sourceCodeEnd":795,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-kernel/src/legacy_migration_barrier/host_fs.rs#L759-L795","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before: entry owned by root, app runs as 'alice'\n// $ sudo tar -xzf backup.tgz -C /home/alice/data\nlet result = snapshot_path_with_access(path, SourceAccess::OwnerControlled);\n// Err: legacy source entry is not owned by the current user: ...\n\n// after: take ownership before migrating\n// $ sudo chown -R alice:alice /home/alice/data\nlet result = snapshot_path_with_access(path, SourceAccess::OwnerControlled);","handlingStrategy":"validation","validationCode":"#[cfg(unix)]\nfn assert_owned_by_current_user(source: &std::path::Path) -> std::io::Result<()> {\n    use std::os::unix::fs::MetadataExt;\n    let uid = nix::unistd::getuid().as_raw();\n    let mut stack = vec![source.to_path_buf()];\n    while let Some(dir) = stack.pop() {\n        for entry in std::fs::read_dir(&dir)? {\n            let path = entry?.path();\n            let md = std::fs::symlink_metadata(&path)?;\n            if md.uid() != uid {\n                return Err(std::io::Error::new(\n                    std::io::ErrorKind::PermissionDenied,\n                    format!(\"not owned by current user: {}\", path.display()),\n                ));\n            }\n            if md.is_dir() {\n                stack.push(path);\n            }\n        }\n    }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"match snapshot_path_with_access(source, SourceAccess::OwnerControlled) {\n    Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied\n        && e.to_string().contains(\"not owned by the current user\") =>\n    {\n        eprintln!(\"fix with: sudo chown -R $(id -u):$(id -g) <source>\");\n    }\n    other => other?,\n}","preventionTips":["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"],"tags":["filesystem","permissions","ownership","unix","rust"],"backgroundTag":"permission-denied","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}