{"record":{"id":"c07b80ff04e414c1","repo":"astrid-runtime/astrid","slug":"durable-capsule-id-version-differs-across-packag","errorCode":null,"errorMessage":"durable capsule {id} version differs across package records","messagePattern":"durable capsule (.+?) version differs across package records","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/astrid-capsule-install/src/storage.rs","lineNumber":270,"sourceCode":"    id: &str,\n    manifest: &CapsuleManifest,\n    metadata: &CapsuleMeta,\n    authority: &InstalledAuthority,\n    manifest_bytes: &[u8],\n    verification: &ArtifactVerification,\n    archive_files: &std::collections::BTreeMap<String, Vec<u8>>,\n) -> anyhow::Result<()> {\n    if authority.schema_version != 1 {\n        bail!(\n            \"durable capsule {id} has unsupported authority schema {}\",\n            authority.schema_version\n        );\n    }\n    if authority.capsule_id != id || manifest.package.name != id {\n        bail!(\"durable capsule {id} identity differs across archive and authority\");\n    }\n    if authority.version != manifest.package.version || metadata.version != authority.version {\n        bail!(\"durable capsule {id} version differs across package records\");\n    }\n    let manifest_digest = crate::authority::digest_manifest(manifest_bytes);\n    if authority.manifest_digest != manifest_digest {\n        bail!(\"durable capsule {id} manifest digest differs from authority receipt\");\n    }\n    if authority.content_digest != verification.content_digest() {\n        bail!(\"durable capsule {id} content digest differs from authority receipt\");\n    }\n    let expected_imports = crate::wit::version_map_to_strings(&manifest.imports, |definition| {\n        definition.version.to_string()\n    });\n    if metadata.imports != expected_imports {\n        bail!(\"durable capsule {id} imports differ between metadata and archive\");\n    }\n    let expected_exports = crate::wit::version_map_to_strings(&manifest.exports, |definition| {\n        definition.version.to_string()\n    });\n    if metadata.exports != expected_exports {","sourceCodeStart":252,"sourceCodeEnd":288,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-capsule-install/src/storage.rs#L252-L288","documentation":"verify_package_identity throws this when the version recorded in the authority receipt, the archive manifest (package.version), and the durable metadata do not all agree. All three records must carry the same version for a capsule to be considered coherently installed; disagreement means one record is stale, from a different release, or was tampered with. This protects consumers from loading an artifact other than the one the authority approved.","triggerScenarios":"read_verified_durable_package_for_owner encounters InstalledAuthority.version != manifest.package.version, or CapsuleMeta.version != authority.version — e.g. after a partial upgrade that updated the archive but not the metadata, or vice versa.","commonSituations":"Upgrading a capsule in place and the metadata write failing midway; restoring only some files from backup so manifest and metadata come from different versions; republishing a capsule at a new version while an old authority receipt is still on disk; sharing install directories between machines with different capsule versions.","solutions":["Reinstall the capsule at the intended version so manifest, metadata, and authority receipt are all rewritten consistently.","Delete the stale durable metadata/authority files for the capsule and re-run the install flow.","Verify which version each record claims and pick one canonical version, then republish/re-approve the capsule at that version.","Restore the whole capsule directory from a single consistent backup instead of partial files."],"exampleFix":"// before: partial upgrade left metadata at old version\n// metadata.version = \"1.0.0\", authority.version = \"1.1.0\"\n// after: remove stale state and reinstall the exact version\nstore.remove_durable(owner, \"my-capsule\")?;\nstore.install(owner, &capsule_archive_v1_1_0)?;","handlingStrategy":"validation","validationCode":"fn versions_agree(manifest: &CapsuleManifest, metadata: &CapsuleMeta, authority: &InstalledAuthority) -> bool {\n    authority.version == manifest.package.version && metadata.version == authority.version\n}","typeGuard":"fn is_coherent_version(meta: &CapsuleMeta, a: &InstalledAuthority) -> bool { meta.version == a.version }","tryCatchPattern":"match store.read_verified_durable_package_for_owner(owner, id) {\n    Ok(pkg) => pkg,\n    Err(e) if e.to_string().contains(\"version differs across package records\") => {\n        store.remove_durable(owner, id)?;\n        store.install(owner, &archive)?\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Never upgrade a capsule by rewriting only some of its records; use the full install/upgrade API.","Back up and restore the entire capsule directory as one unit.","Pin explicit versions instead of mutating installed capsules in place.","Check install-directory writes completed (no partial upgrades) after crashes."],"tags":["integrity","capsule","version-mismatch","rust"],"backgroundTag":"version-mismatch","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"}