astrid-runtime/astrid · error · io::Error
layout migration receipt destination path does not match the
Error message
layout migration receipt destination path does not match the live Astrid volume
What it means
After resolving the live path's canonical parent and file name, verify_receipt_destination_is_live_path compares it against the receipt's physical_path(destination). If the receipt's recorded destination differs from the canonicalized live volume path, this InvalidData error is raised: the migration receipt does not describe the volume currently in use.
Source
Thrown at crates/astrid-core/src/dirs_layout_records.rs:212
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)
}
#[cfg(unix)]
#[expect(
clippy::unnecessary_wraps,
reason = "the cross-platform receipt decoder has one fallible signature"
)]View on GitHub (pinned to affd8760f4)
Solutions
- Regenerate the layout migration receipt so its destination identity matches the canonical live path.
- Restore the volume file to the exact path recorded in the receipt.
- Diff the receipt's destination against `readlink -f <live_path>` and reconcile whichever is stale.
Example fix
// before: receipt written for old location
// destination = /mnt/data/old/volume.bin
// after: move volume back or rewrite receipt
std::fs::rename("/mnt/data/new/volume.bin", "/mnt/data/old/volume.bin")?; Defensive patterns
Strategy: validation
Validate before calling
let canonical = std::fs::canonicalize(&live_path)?;
if canonical != /* path from receipt */ {
return Err("receipt destination does not match live volume; reissue receipt");
} Try / catch
match retire_verified_legacy_source(...) {
Err(e) if e.to_string().contains("does not match the live Astrid volume") => regenerate_receipt_and_retry(),
other => other,
} Prevention
- Always regenerate receipts after moving or renaming the volume file.
- Compare `readlink -f` of the live path against the receipt before retiring.
- Avoid copying receipts between volumes or machines.
When it happens
Trigger: Called via retire_verified_legacy_source when canonical_parent.join(file_name) != physical_path(destination) — e.g. the volume was moved/renamed after the receipt was written, or the receipt records a stale or different destination identity.
Common situations: Volume file moved to a new mount point or renamed; receipt copied from another machine or volume; a symlinked directory canonicalizes to a different real location than the receipt recorded.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- layout path has no existing directory ancestor: {}
- layout migration destination is redirected or not a regular
- live Astrid volume has no parent
- live Astrid volume has no name
- layout migration source is redirected or not a directory: {}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/ec86dd582506830a.
Report an issue: GitHub.