{"record":{"id":"672c9533ee628774","repo":"astrid-runtime/astrid","slug":"invalid-receipt-destination-destination-error","errorCode":null,"errorMessage":"invalid receipt destination {destination}: {error}","messagePattern":"invalid receipt destination (.+?): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-kernel/src/principal_home_migration/mod.rs","lineNumber":741,"sourceCode":") -> io::Result<()> {\n    let filesystem = AstridFilesystem::new(store.content(), StateOwner::Principal(uid));\n    let mut summary = InventorySummary::default();\n    let mut count = 0_u64;\n    for page_number in 0..receipt.page_count.get() {\n        let page = read_page(home, uid, page_number)?;\n        if page.page != page_number {\n            return Err(conflict_path(\n                &receipt_path_for_display(uid),\n                \"receipt page sequence is not canonical\",\n            ));\n        }\n        for entry in page.entries {\n            summary.update(&entry)?;\n            count = count\n                .checked_add(1)\n                .ok_or_else(|| io::Error::other(\"receipt entry count overflow\"))?;\n            let destination = FilesystemPath::new(entry.destination.clone()).map_err(|error| {\n                io::Error::new(\n                    io::ErrorKind::InvalidData,\n                    format!(\"invalid receipt destination {}: {error}\", entry.destination),\n                )\n            })?;\n            match entry.kind {\n                EntryKind::Directory => {\n                    let actual = filesystem\n                        .stat(&destination)\n                        .map_err(|error| storage_error(&error))?;\n                    if actual.kind() != FilesystemEntryKind::Directory {\n                        return Err(conflict_fs(\n                            &destination,\n                            \"receipt destination is not a directory\",\n                        ));\n                    }\n                },\n                EntryKind::File => verify_file_content(&filesystem, &destination, &entry)?,\n            }","sourceCodeStart":723,"sourceCodeEnd":759,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-kernel/src/principal_home_migration/mod.rs#L723-L759","documentation":"Raised by verify_destinations when a receipt entry's destination cannot be parsed as a FilesystemPath during post-migration verification. Verification reads back all receipt pages and revalidates each destination; a parse failure aborts verification with InvalidData.","triggerScenarios":"Calling migrate_one_principal -> verify_destinations when a stored receipt entry has a destination string FilesystemPath::new rejects — the same class of malformed logical path as [1505] but discovered at verification time.","commonSituations":"Receipt files corrupted on disk or partially written by a crashed run, receipts written by an incompatible older version, manual editing of receipt JSON.","solutions":["Validate receipt files before verification and repair or drop invalid entries","Restore receipts from backup if corrupted","Regenerate the migration by clearing receipts and re-running migration","Check the writer version that produced the receipts for a format bug"],"exampleFix":"// before: verifying corrupt receipts aborts\nverify_destinations(&filesystem, &receipts, &summary)?;\n// after: pre-validate receipts\nlet receipts = load_and_validate_receipts(&receipts_dir)?;\nverify_destinations(&filesystem, &receipts, &summary)?;","handlingStrategy":"validation","validationCode":"fn receipts_parse(dir: &Path) -> bool {\n    load_receipt_pages(dir).map(|pages| pages.iter().all(|p| p.entries.iter().all(|e| FilesystemPath::new(e.destination.clone()).is_ok()))).unwrap_or(false)\n}","typeGuard":"fn valid_receipt_entry(e: &Entry) -> bool { FilesystemPath::new(e.destination.clone()).is_ok() }","tryCatchPattern":"match verify_destinations(&fs, &receipts, &summary) {\n    Err(e) if e.kind() == io::ErrorKind::InvalidData => restore_receipts_from_backup()?,\n    Err(e) => return Err(e),\n    Ok(()) => {},\n}","preventionTips":["Back up receipt files before verification","Detect partial writes by checksumming receipt files","Validate receipts immediately after migration, before cleanup"],"tags":["validation","paths","receipts","migration"],"backgroundTag":"invalid-url-format","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}