{"record":{"id":"b3094a1df6d768ed","repo":"astrid-runtime/astrid","slug":"live-principal-migration-receipt-is-missing","errorCode":null,"errorMessage":"live principal migration receipt is missing: {}","messagePattern":"live principal migration receipt is missing: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-kernel/src/legacy_migration_barrier/ledger.rs","lineNumber":441,"sourceCode":"            continue;\n        }\n        if component.name.starts_with(\"system:\") {\n            return Err(io::Error::new(\n                io::ErrorKind::InvalidData,\n                format!(\n                    \"required system migration receipt is missing: {}\",\n                    component.name\n                ),\n            ));\n        }\n        // A current UID's immutable receipt/marker cannot silently disappear.\n        // Deleted historical UIDs are intentionally allowed to have no live\n        // projection, and an originally absent component remains absent when\n        // its ledger proof was explicitly recorded as such.\n        if is_live_principal_component(&component.name, directory)\n            && (component.source.present || !component.destination_proof.is_absent())\n        {\n            return Err(io::Error::new(\n                io::ErrorKind::InvalidData,\n                format!(\n                    \"live principal migration receipt is missing: {}\",\n                    component.name\n                ),\n            ));\n        }\n        if let Some(uid) = principal_component_uid(&component.name)\n            && !directory.contains_uid(uid)\n            && component.name.ends_with(\":home\")\n        {\n            let receipt = home\n                .migrations_dir()\n                .join(format!(\"principal-home-{uid}.json\"));\n            let actual = destination_file_proof(&receipt)?;\n            if actual != component.destination_proof {\n                return Err(io::Error::new(\n                    io::ErrorKind::InvalidData,","sourceCodeStart":423,"sourceCodeEnd":459,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-kernel/src/legacy_migration_barrier/ledger.rs#L423-L459","documentation":"For principal components that currently have a live projection in the destination directory, `validate_existing_proofs` requires a receipt — unless the component is absent both at source and per the recorded (absent) proof. If a live principal component is missing its receipt despite being present at source or not recorded as absent, this error is thrown. Deleted historical UIDs are intentionally exempt (no live projection), so the failure indicates ledger/receipts inconsistency for a component that should have one.","triggerScenarios":"validate_existing_proofs finds is_live_principal_component(name, directory) true while component.source.present is true or component.destination_proof is not the explicit absent marker, and no receipt exists for it.","commonSituations":"The user was recreated (same UID) after migrating, so the component is live again but no new receipt exists; receipts were deleted by cleanup scripts; the ledger was restored from a snapshot taken before the component existed.","solutions":["Re-run resume_existing_layout / migration to generate a receipt for the now-live principal component.","If the component is genuinely absent, ensure the ledger records the proof as explicitly absent so the exemption applies.","Audit cleanup jobs so they do not delete receipts from migrations_dir while components remain live."],"exampleFix":"// before: cleanup script deleted receipts but component is live on disk\n$ astrid migrate  # regenerate receipts for live components\n// after: exclude migrations_dir from cleanup cron","handlingStrategy":"try-catch","validationCode":"if is_live_principal_component(&name, &dir) && source_present && !receipt_exists(&name) {\n    eprintln!(\"live principal component {} lacks a receipt\", name);\n}","typeGuard":null,"tryCatchPattern":"match resume_existing_layout(...) {\n    Err(e) if e.to_string().contains(\"live principal migration receipt is missing\") => {\n        eprintln!(\"re-run migration to issue receipts for live principal components\");\n    }\n    r => r?,\n}","preventionTips":["Exclude migrations_dir from cleanup scripts and log-rotation jobs.","Re-run migration after recreating users (UID reuse) so live components get receipts.","Verify receipts exist for every live principal component before resuming."],"tags":["security","ledger","migration","validation"],"backgroundTag":"invalid-state-transition","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}