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

live Astrid volume has no name

Error message

live Astrid volume has no name

What it means

verify_receipt_destination_is_live_path extracts the file-name component of the live Astrid volume path after checking its parent. If the path has no final file-name component (e.g. it ends in ".." or is a directory root), file_name() returns None and this InvalidInput error is raised. The name is needed to join with the canonicalized parent for the receipt comparison.

Source

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

                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)
}

fn physical_path(destination: &LayoutTreeIdentityV1) -> io::Result<PathBuf> {
    let bytes = hex::decode(&destination.physical_path_hex)
        .map_err(|error| io::Error::other(format!("decode layout destination path: {error}")))?;
    encoded_bytes_to_os_string(bytes).map(PathBuf::from)

View on GitHub (pinned to affd8760f4)

Solutions

  1. Normalize the live path (strip trailing "."/"..") so it terminates in an actual file name.
  2. Use path.canonicalize() or clean the configured value before invoking retirement.
  3. Verify the config value points directly at the volume file, not its containing directory.

Example fix

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

Strategy: validation

Validate before calling

let live = Path::new(&volume_config);
if live.file_name().is_none() {
    return Err("live volume path must end in a concrete file name");
}

Try / catch

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

Prevention

When it happens

Trigger: Called via retire_verified_legacy_source with a live_path such as "/some/dir/.." or "/" where Path::file_name() yields None, immediately after the parent check succeeds.

Common situations: A trailing ".." or "." left in a configured path; path normalization not performed before passing the live volume path; template-expanded config leaving a dangling path segment.

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