{"record":{"id":"9d588acc0bcdf3fb","repo":"astrid-runtime/astrid","slug":"legacy-capsule-id-authority-verification-produce","errorCode":null,"errorMessage":"legacy capsule {id} authority verification produced no receipt","messagePattern":"legacy capsule (.+?) authority verification produced no receipt","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-capsule-install/src/storage/migration.rs","lineNumber":156,"sourceCode":"        }\n        let meta_bytes = fs::read(target.join(\"meta.json\"))\n            .with_context(|| format!(\"read legacy capsule metadata {id}\"))?;\n        let meta: CapsuleMeta = serde_json::from_slice(&meta_bytes)\n            .with_context(|| format!(\"decode legacy capsule metadata {id}\"))?;\n        if meta.version != manifest.package.version {\n            bail!(\"legacy capsule metadata version differs for {id}\");\n        }\n        // Released pre-authority installs are admitted only through the\n        // existing one-time verifier. It pins their exact manifest,\n        // capabilities, and executable before any durable publication.\n        // Relocated homes keep receipts hashed from a previous absolute\n        // path; rebind a unique leftover onto this target first.\n        rebind_relocated_legacy_authority_receipt(home, &target, &manifest, workspace_targets)\n            .with_context(|| format!(\"rebind relocated leftover authority for {id}\"))?;\n        verify_installed_authority(home, &target, &manifest)\n            .with_context(|| format!(\"verify legacy capsule authority {id}\"))?;\n        let authority = read_installed_authority(home, &target)?.ok_or_else(|| {\n            anyhow::anyhow!(\"legacy capsule {id} authority verification produced no receipt\")\n        })?;\n        if authority.capsule_id != id || authority.version != manifest.package.version {\n            bail!(\"legacy capsule authority identity differs for {id}\");\n        }\n        let source_authority_bytes = read_installed_authority_bytes(home, &target)?\n            .ok_or_else(|| anyhow::anyhow!(\"legacy capsule {id} authority receipt disappeared\"))?;\n        let archive = canonical_legacy_archive(home, &target, &meta, &manifest)?;\n        let verification = artifact::verify_archive_bytes(&archive)\n            .with_context(|| format!(\"verify canonical legacy capsule archive {id}\"))?;\n        let mut durable_authority = authority;\n        verification\n            .content_digest()\n            .clone_into(&mut durable_authority.content_digest);\n        let durable_authority_bytes = serde_json::to_vec_pretty(&durable_authority)\n            .with_context(|| format!(\"serialize durable legacy capsule authority {id}\"))?;\n        let package = CapsulePackage::new(archive, meta_bytes, durable_authority_bytes);\n        let expectation = match registry.get_snapshot(&owner, id)? {\n            None => CapsuleInstallExpectation::Absent,","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-capsule-install/src/storage/migration.rs#L138-L174","documentation":"After verifying a legacy capsule's authority (`verify_installed_authority`), the migration reads back the installed authority receipt with `read_installed_authority`. If that returns `None` — no receipt file exists on disk — this error is raised. It signals an inconsistent install state: verification logically succeeded but the receipt artifact is missing, so the migration cannot construct a durable authority record.","triggerScenarios":"Calling `migrate_native_capsules_with_report` on a legacy capsule whose authority receipt file is absent under the install target, or whose `rebind_relocated_legacy_authority_receipt` step silently skipped because no relocated leftover matched, leaving nothing for `read_installed_authority` to find.","commonSituations":"Partially completed previous migration or install that wrote verification output but not the receipt; manual deletion/cleanup of receipt files inside an installed capsule; capsule directories copied between machines without their receipt sidecar files.","solutions":["Reinstall or re-run migration for the affected capsule so the authority receipt is regenerated during install","Restore the missing receipt file from a good install of the same capsule id/version, or re-run `verify_installed_authority` followed by the receipt-persisting step in your install flow","Check the relocated-receipt logic: if receipts live under path-hashed locations, ensure `rebind_relocated_legacy_authority_receipt` can find the leftover (matching capsule id and version) before migration"],"exampleFix":"// before\n// receipt file manually removed during cleanup\nrm ~/.capsule/installed/legacy-tools/.authority/receipt.json\nmigrate_native_capsules(home)?; // \"legacy capsule legacy-tools authority verification produced no receipt\"\n\n// after\n// reinstall so the receipt is written, then migrate\ncapsule install legacy-tools@1.2.3\nmigrate_native_capsules(home)?;","handlingStrategy":"validation","validationCode":"fn assert_authority_receipt_present(home: &Path, target: &Path) -> anyhow::Result<()> {\n    let receipt = read_installed_authority(home, target)\n        .context(\"read installed authority\")?;\n    anyhow::ensure!(receipt.is_some(),\n        \"capsule {} has no authority receipt; reinstall before migrating\",\n        target.display());\n    Ok(())\n}\n// run per legacy target before migrate_native_capsules\nfor target in legacy_targets { assert_authority_receipt_present(home, &target)?; }","typeGuard":"fn has_authority_receipt(home: &Path, target: &Path) -> bool {\n    matches!(read_installed_authority(home, target), Ok(Some(_)))\n}","tryCatchPattern":"match migrate_native_capsules(home) {\n    Err(e) if e.to_string().contains(\"produced no receipt\") => {\n        // reinstall the named capsule to regenerate its receipt, then retry migration\n    }\n    Err(e) => return Err(e),\n    Ok(r) => r,\n}","preventionTips":["Never manually delete files inside installed capsule directories; uninstall/reinstall instead","Migrate capsules in a single pass rather than interrupting mid-run, to avoid half-written receipt state","When copying capsule homes between machines, copy receipt sidecars along with the capsule contents","Ensure the relocated-receipt rebind step has matching id/version leftovers when using path-hashed receipt layouts"],"tags":["migration","authority","receipt","state-inconsistency","rust"],"backgroundTag":"file-not-found","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"}