{"record":{"id":"6477f9b90e2de462","repo":"astrid-runtime/astrid","slug":"durable-capsule-id-conflicts-with-legacy-native","errorCode":null,"errorMessage":"durable capsule {id} conflicts with legacy native content","messagePattern":"durable capsule (.+?) conflicts with legacy native content","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-capsule-install/src/storage/migration.rs","lineNumber":178,"sourceCode":"        }\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,\n            Some(snapshot) if snapshot.package() == &package => {\n                CapsuleInstallExpectation::Generation(snapshot.generation())\n            },\n            Some(_) => bail!(\"durable capsule {id} conflicts with legacy native content\"),\n        };\n        registry.install(&owner, id, &package, expectation)?;\n        let readback = registry\n            .get_snapshot(&owner, id)?\n            .ok_or_else(|| anyhow::anyhow!(\"durable capsule {id} disappeared after publish\"))?;\n        if readback.package() != &package {\n            bail!(\"durable capsule {id} failed byte-for-byte readback\");\n        }\n        read_verified_durable_package_for_owner(store, &owner, id)?.ok_or_else(|| {\n            anyhow::anyhow!(\"durable capsule {id} failed authoritative verification\")\n        })?;\n        astrid_core::platform_fs::verify_no_redirects(&target)\n            .with_context(|| format!(\"verify legacy capsule {id} before retirement\"))?;\n        let final_archive = canonical_legacy_archive(home, &target, &meta, &manifest)?;\n        if final_archive != package.archive {\n            bail!(\"legacy capsule {id} changed before retirement\");\n        }\n        if fs::read(target.join(\"meta.json\"))? != package.metadata {","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-capsule-install/src/storage/migration.rs#L160-L196","documentation":"Before installing the migrated legacy package into the durable registry, migration checks the existing durable snapshot. If a durable capsule with the same id already exists and its bytes differ from the legacy-derived package, migration aborts rather than overwriting divergent content.","triggerScenarios":"A durable capsule with the same id was already installed from a different source/build; the legacy install and a prior migration or store install have diverged; id collision between two different capsules.","commonSituations":"Same capsule id installed both durably (new system) and natively (legacy system) with different versions or builds; duplicate ids across development and release builds.","solutions":["Remove the conflicting durable capsule (or the legacy one) so only one source of truth remains","Rebuild the legacy capsule to match the durable content, or vice versa","Migrate under a corrected unique id if two genuinely different capsules collide","Back up and clear the conflicting entry, then re-run migration"],"exampleFix":"// before\nregistry id \"my-capsule\" holds build A; legacy dir holds build B\n// after\nregistry.remove(owner, \"my-capsule\") then re-run migration to publish build B","handlingStrategy":"validation","validationCode":"// before migrating, ensure the durable registry holds no conflicting id\nfor id in legacy_ids {\n    if store.capsules().get_snapshot(&owner, &id)?.is_some() {\n        eprintln!(\"durable capsule {id} already exists; resolve before migrating\");\n    }\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = migrate_native_capsules(home, store) {\n    if e.to_string().contains(\"conflicts with legacy native content\") {\n        eprintln!(\"remove or align the conflicting durable capsule, then retry\");\n    } else { return Err(e); }\n}","preventionTips":["Avoid installing the same capsule id both durably and natively","Use unique ids per capsule variant (dev vs release)","Run migration before creating new durable installs of legacy ids","Snapshot the store before migration so conflicts can be rolled back"],"tags":["migration","conflict","registry","capsule","duplicate-id"],"backgroundTag":"file-already-exists","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"}