astrid-runtime/astrid · error

legacy distro

Error message

legacy distro {path}: {detail}

What it means

This io::Error with ErrorKind::InvalidData wraps any problem found while inspecting or migrating a legacy distro directory. It is the generic rejection path of the legacy distro migration code: the path exists but fails a structural or content check. The {detail} suffix carries the specific reason.

Solutions

  1. Read the {detail} portion of the message to identify the exact failed check
  2. Inspect the legacy distro directory at {path} against the expected legacy layout
  3. Re-create or repair the legacy distro using the tooling that produced it originally
  4. Skip or quarantine the invalid distro if it is no longer needed

Example fix

// before: migration aborts on invalid distro
migrate_legacy_distro(path)?;
// after: validate first and skip bad entries
if let Err(e) = validate_legacy_distro(path) {
    log::warn!("skipping invalid distro {path}: {e}");
    return Ok(());
}
Defensive patterns

Strategy: try-catch

Validate before calling

fn distro_looks_valid(path: &Path) -> bool {
    path.is_dir() && path.join("identifier").is_file()
}

Type guard

fn is_valid_distro_path(p: &Path) -> bool { p.is_dir() && p.metadata().is_ok() }

Try / catch

match migrate_one(path) {
    Err(e) if e.kind() == io::ErrorKind::InvalidData => warn!("skip distro {}: {e}", path.display()),
    Err(e) => return Err(e),
    Ok(()) => {},
}

Prevention

When it happens

Trigger: Calling invalid(path, detail) from legacy_distro_destination_proof, legacy_distro_init_destination_proof, migrate_one, validate, identifier, or nonempty when a legacy distro path fails validation — e.g. missing/empty identifier, bad destination proof, or unreadable metadata.

Common situations: Hand-copied distro directories missing expected files, legacy distros produced by older versions with a different layout, or paths containing unexpected content after manual edits.

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/1f2db2334eb837cc. Report an issue: GitHub.

Appendix: source

Thrown at crates/astrid-kernel/src/principal_distro_migration.rs:562

#[cfg(unix)]
fn sync_parent(path: &Path) -> io::Result<()> {
    if let Some(parent) = path.parent() {
        File::open(parent)?.sync_all()?;
    }
    Ok(())
}

#[cfg(not(unix))]
// Windows publication is already write-through; keep the shared fallible
// signature so migration call sites remain platform-independent.
#[allow(clippy::unnecessary_wraps)]
fn sync_parent(_path: &Path) -> io::Result<()> {
    Ok(())
}

fn invalid(path: &Path, detail: &str) -> io::Error {
    io::Error::new(
        io::ErrorKind::InvalidData,
        format!("legacy distro {}: {detail}", path.display()),
    )
}

fn conflict(path: &Path, detail: &str) -> io::Error {
    io::Error::new(
        io::ErrorKind::AlreadyExists,
        format!("legacy distro conflict at {}: {detail}", path.display()),
    )
}

#[cfg(test)]
mod tests {
    use super::*;

    fn lock_text() -> &'static str {
        "schema-version = 1\n\n[distro]\nid = \"example\"\nversion = \"1.0.0\"\nresolved-at = \"2026-01-01T00:00:00Z\"\n"

View on GitHub (pinned to affd8760f4)