astrid-runtime/astrid · error

legacy audit retirement source is outside the default princi

Error message

legacy audit retirement source is outside the default principal audit path

What it means

retire_legacy_audit_dir only retires the exact default principal audit directory (home.principal_home(&PrincipalId::default()).audit_dir()). If the caller passes any other source path, the function rejects it with InvalidInput before performing any traversal or deletion, as a guard against retiring arbitrary directories. The message carries no path since it is a programmatic argument check.

Source

Thrown at crates/astrid-kernel/src/legacy_migration_barrier/host_fs.rs:450

                format!(
                    "unsupported legacy audit source {}; only the default principal source is admitted",
                    audit_source.display()
                ),
            ));
        }
    }
    Ok(default_source_present)
}

/// Retire the imported default audit tree through a private staging rename.
/// The rename makes interrupted deletion resumable, while every pre/post
/// traversal revalidates no-follow, regular-entry, device, and mount bounds.
#[cfg(not(unix))]
pub(super) fn retire_legacy_audit_dir(home: &AstridHome, source: &Path) -> io::Result<()> {
    let retired = home.migrations_dir().join("audit-principal-home.retired");
    let expected = home.principal_home(&PrincipalId::default()).audit_dir();
    if source != expected {
        return Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            "legacy audit retirement source is outside the default principal audit path",
        ));
    }
    astrid_core::platform_fs::verify_no_redirects(source.parent().ok_or_else(|| {
        io::Error::new(
            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 fs::symlink_metadata(source) {
        Ok(metadata) if metadata.file_type().is_symlink() || !metadata.is_dir() => {
            return Err(io::Error::new(
                io::ErrorKind::InvalidData,
                format!(
                    "legacy audit source is not a regular directory: {}",

View on GitHub (pinned to affd8760f4)

Solutions

  1. Pass exactly home.principal_home(&PrincipalId::default()).audit_dir() as the source argument.
  2. Normalize the source path (canonicalize or construct it from AstridHome APIs) instead of assembling it from strings.
  3. If migrating a non-default principal's audit dir, do not use this API — it only supports the default principal.
  4. Check for trailing slashes or duplicated separators in the path you pass and remove them.

Example fix

// before
retire_legacy_audit_dir(&home, &Path::from("/home/u/.astrid/principals/other/audit"))?;
// after
let source = home.principal_home(&PrincipalId::default()).audit_dir();
retire_legacy_audit_dir(&home, &source)?;
Defensive patterns

Strategy: type-guard

Validate before calling

fn source_is_default(home: &AstridHome, source: &std::path::Path) -> bool {
    source == home.principal_home(&PrincipalId::default()).audit_dir()
}

Type guard

fn expected_retirement_source(home: &AstridHome) -> std::path::PathBuf {
    home.principal_home(&PrincipalId::default()).audit_dir()
}

Try / catch

match result {
    Err(e) if e.kind() == std::io::ErrorKind::InvalidInput && e.to_string().contains("outside the default principal audit path") => {
        // rebuild the path via AstridHome APIs and retry
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling retire_legacy_audit_dir(home, source) (via migrate_legacy_audit) with a source path that is not byte-identical to the default principal audit dir — e.g. a trailing slash difference, a non-default principal's audit dir, or a hand-constructed path (host_fs.rs:449).

Common situations: Custom migration scripts passing their own path; tests exercising retirement with a fabricated source; path normalization differences (//, trailing separator, symlinked parents) between the caller's path and the computed expected path.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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