astrid-runtime/astrid · error

ordinary legacy file is not owned by the current user

Error message

ordinary legacy file is not owned by the current user: {path}

What it means

Raised by validate_regular_file when an ordinary legacy file's owner uid differs from the current process uid (unix only). Migration refuses to ingest files the current user does not own, since trusting foreign-owned files would be a security risk. ErrorKind::PermissionDenied.

Solutions

  1. chown the legacy files to the current user (e.g. sudo chown -R $(id -u) <path>)
  2. Re-copy the legacy home as the current user without sudo
  3. Run the migration as the owner of the files
  4. Exclude the foreign-owned files from the legacy source tree

Example fix

// before: migration fails on root-owned files
sudo cp -r /old/home ~/legacy-home   # files owned by root
// after: take ownership first
sudo chown -R $(id -u):$(id -g) ~/legacy-home
Defensive patterns

Strategy: validation

Validate before calling

#[cfg(unix)]
fn all_files_owned_by_me(root: &Path) -> bool {
    use std::os::unix::fs::MetadataExt;
    walk(root).all(|p| p.metadata().map(|m| m.uid() == nix::unistd::getuid().as_raw()).unwrap_or(false))
}

Type guard

#[cfg(unix)]
fn owned_by_current_user(m: &std::fs::Metadata) -> bool {
    use std::os::unix::fs::MetadataExt;
    m.uid() == nix::unistd::getuid().as_raw()
}

Try / catch

match migrate(...) {
    Err(e) if e.kind() == io::ErrorKind::PermissionDenied => {
        eprintln!("fix ownership: chown -R $(id -u) <legacy home>");
        Err(e)
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling digest_file or publish_directory_files (via migrate_legacy_principal_homes) when a regular file under the legacy source tree has metadata.uid() != getuid().

Common situations: Legacy homes copied with sudo/root ownership, files restored from backups as root, shared multi-user machines where another user created files in the migrated tree.

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


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

Appendix: source

Thrown at crates/astrid-kernel/src/principal_home_migration/mod.rs:873

    }
    Ok((
        ByteCount::new(bytes),
        ContentDigest::from_blake3(hasher.finalize()),
    ))
}

fn validate_regular_file(path: &Path) -> io::Result<()> {
    let metadata = fs::symlink_metadata(path)?;
    if metadata.file_type().is_symlink() || !metadata.is_file() {
        return Err(invalid_source(path, "ordinary entry is not a regular file"));
    }
    astrid_core::platform_fs::verify_no_redirects(path)?;
    #[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!(
                    "ordinary legacy file is not owned by the current user: {}",
                    path.display()
                ),
            ));
        }
        if metadata.mode() & 0o022 != 0 {
            return Err(io::Error::new(
                io::ErrorKind::PermissionDenied,
                format!(
                    "ordinary legacy file is group/world writable: {}",
                    path.display()
                ),
            ));
        }
    }
    Ok(())

View on GitHub (pinned to affd8760f4)