astrid-runtime/astrid · error

legacy audit retirement is ambiguous: {retired}

Error message

legacy audit retirement is ambiguous: {retired}

What it means

After confirming the source audit directory exists, the routine checks that the retirement marker migrations_dir/audit-principal-home.retired does not already exist. If it does, the intended rename target is occupied, making the retirement state ambiguous (previous data vs. new move), so it aborts with AlreadyExists rather than overwrite anything.

Source

Thrown at crates/astrid-kernel/src/lib.rs:4276

            std::io::ErrorKind::InvalidInput,
            "legacy audit source has no parent",
        )
    })?)?;
    astrid_core::platform_fs::ensure_private_directory(&home.migrations_dir())?;
    astrid_core::platform_fs::verify_no_redirects(&home.migrations_dir())?;
    match std::fs::symlink_metadata(source) {
        Ok(metadata) if metadata.file_type().is_symlink() || !metadata.is_dir() => {
            return Err(std::io::Error::new(
                std::io::ErrorKind::InvalidData,
                format!(
                    "legacy audit source is not a regular directory: {}",
                    source.display()
                ),
            ));
        },
        Ok(_) => {
            if std::fs::symlink_metadata(&retired).is_ok() {
                return Err(std::io::Error::new(
                    std::io::ErrorKind::AlreadyExists,
                    format!(
                        "legacy audit retirement is ambiguous: {}",
                        retired.display()
                    ),
                ));
            }
            let root_device = audit_tree_device(&std::fs::symlink_metadata(source)?);
            validate_audit_tree(source, root_device)?;
            astrid_core::platform_fs::rename_with_write_through(source, &retired)?;
            sync_audit_directory(source.parent().ok_or_else(|| {
                std::io::Error::new(
                    std::io::ErrorKind::InvalidInput,
                    "legacy audit source has no parent",
                )
            })?)?;
            sync_audit_directory(&home.migrations_dir())?;
            validate_audit_tree(&retired, root_device)?;

View on GitHub (pinned to affd8760f4)

Solutions

  1. Verify the existing audit-principal-home.retired contains the old audit data and delete it (or move it aside) before re-running
  2. Check whether the previous migration actually completed and skip the migration entirely if it did
  3. Rename the stale target (e.g. audit-principal-home.retired.bak-<date>) to unblock the rename

Example fix

// before
migrations/audit-principal-home.retired/   (stale target blocks rename)
// after
mv migrations/audit-principal-home.retired migrations/audit-principal-home.retired.bak-2026-09-09
Defensive patterns

Strategy: validation

Validate before calling

let retired = home.migrations_dir().join("audit-principal-home.retired");
if std::fs::symlink_metadata(&retired).is_ok() {
    // resolve or archive the stale target before re-running the migration
}

Type guard

fn retirement_target_is_free(home: &Home) -> bool {
    std::fs::symlink_metadata(home.migrations_dir().join("audit-principal-home.retired")).is_err()
}

Try / catch

match run_migration() {
    Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists
        && e.to_string().contains("retirement is ambiguous") => {
        // archive the stale retired dir (e.g. .bak-<date>) and retry once
    }
    r => r?,
}

Prevention

When it happens

Trigger: Re-running the legacy audit migration after a previous retirement already created audit-principal-home.retired, or when a stale/partial retirement target directory exists in migrations_dir.

Common situations: Retrying an upgrade that previously half-completed; restoring backups that recreated the retired directory; running the migration on a copied home directory that already contains the marker.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


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