astrid-runtime/astrid · error · io::Error

live Astrid volume has no parent

Error message

live Astrid volume has no parent

What it means

verify_receipt_destination_is_live_path needs the parent directory of the live Astrid volume path to canonicalize and compare it against the receipt's recorded destination. If the live path has no parent component (i.e. it is a bare root path like "/" with no file-name portion for its parent lookup), this io::Error with InvalidInput is raised. This is essentially a degenerate-path guard.

Source

Thrown at crates/astrid-core/src/dirs_layout_records.rs:199

    let metadata = std::fs::symlink_metadata(&path)?;
    if metadata.file_type().is_symlink() || !metadata.is_file() {
        return Err(io::Error::new(
            io::ErrorKind::InvalidData,
            format!(
                "layout migration destination is redirected or not a regular file: {}",
                path.display()
            ),
        ));
    }
    crate::platform_fs::verify_no_redirects(&path)
}

pub(super) fn verify_receipt_destination_is_live_path(
    destination: &LayoutTreeIdentityV1,
    live_path: &Path,
) -> io::Result<()> {
    let parent = live_path.parent().ok_or_else(|| {
        io::Error::new(
            io::ErrorKind::InvalidInput,
            "live Astrid volume has no parent",
        )
    })?;
    let file_name = live_path.file_name().ok_or_else(|| {
        io::Error::new(
            io::ErrorKind::InvalidInput,
            "live Astrid volume has no name",
        )
    })?;
    let canonical_parent = std::fs::canonicalize(parent)?;
    if physical_path(destination)? != canonical_parent.join(file_name) {
        return Err(io::Error::new(
            io::ErrorKind::InvalidData,
            "layout migration receipt destination path does not match the live Astrid volume",
        ));
    }
    verify_receipt_destination_authority(destination)

View on GitHub (pinned to affd8760f4)

Solutions

  1. Fix the configured live volume path so it points at a file inside a directory, not the filesystem root.
  2. Check the config/env value that supplies the live path and ensure it includes a parent directory and file name.
  3. Log/print the live path before calling retire_verified_legacy_source to confirm it is non-root.

Example fix

// before
let live_path = Path::new("/");
// after
let live_path = Path::new("/var/lib/astrid/volume.bin");
Defensive patterns

Strategy: validation

Validate before calling

let live = Path::new(&volume_config);
if live.parent().is_none() || live == Path::new("/") {
    return Err("live volume path must be a file inside a directory, not the root");
}

Try / catch

match retire_verified_legacy_source(...) {
    Err(e) if e.kind() == std::io::ErrorKind::InvalidInput && e.to_string().contains("no parent") => fix_volume_config(),
    other => other,
}

Prevention

When it happens

Trigger: verify_receipt_destination_is_live_path is called (via retire_verified_legacy_source) with live_path == "/" or another path whose Path::parent() returns None, so parent extraction fails before file_name extraction.

Common situations: Misconfigured volume path pointing at the filesystem root instead of a file inside a directory; an env var or config value like ASTRID_VOLUME="/" passed through unchanged; programmatic construction of the live path that dropped the file component.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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