astrid-runtime/astrid · error
durable capsule {id} conflicts with legacy native content
Error message
durable capsule {id} conflicts with legacy native content What it means
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.
Source
Thrown at crates/astrid-capsule-install/src/storage/migration.rs:178
}
let source_authority_bytes = read_installed_authority_bytes(home, &target)?
.ok_or_else(|| anyhow::anyhow!("legacy capsule {id} authority receipt disappeared"))?;
let archive = canonical_legacy_archive(home, &target, &meta, &manifest)?;
let verification = artifact::verify_archive_bytes(&archive)
.with_context(|| format!("verify canonical legacy capsule archive {id}"))?;
let mut durable_authority = authority;
verification
.content_digest()
.clone_into(&mut durable_authority.content_digest);
let durable_authority_bytes = serde_json::to_vec_pretty(&durable_authority)
.with_context(|| format!("serialize durable legacy capsule authority {id}"))?;
let package = CapsulePackage::new(archive, meta_bytes, durable_authority_bytes);
let expectation = match registry.get_snapshot(&owner, id)? {
None => CapsuleInstallExpectation::Absent,
Some(snapshot) if snapshot.package() == &package => {
CapsuleInstallExpectation::Generation(snapshot.generation())
},
Some(_) => bail!("durable capsule {id} conflicts with legacy native content"),
};
registry.install(&owner, id, &package, expectation)?;
let readback = registry
.get_snapshot(&owner, id)?
.ok_or_else(|| anyhow::anyhow!("durable capsule {id} disappeared after publish"))?;
if readback.package() != &package {
bail!("durable capsule {id} failed byte-for-byte readback");
}
read_verified_durable_package_for_owner(store, &owner, id)?.ok_or_else(|| {
anyhow::anyhow!("durable capsule {id} failed authoritative verification")
})?;
astrid_core::platform_fs::verify_no_redirects(&target)
.with_context(|| format!("verify legacy capsule {id} before retirement"))?;
let final_archive = canonical_legacy_archive(home, &target, &meta, &manifest)?;
if final_archive != package.archive {
bail!("legacy capsule {id} changed before retirement");
}
if fs::read(target.join("meta.json"))? != package.metadata {View on GitHub (pinned to affd8760f4)
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
Example fix
// before registry id "my-capsule" holds build A; legacy dir holds build B // after registry.remove(owner, "my-capsule") then re-run migration to publish build B
Defensive patterns
Strategy: validation
Validate before calling
// before migrating, ensure the durable registry holds no conflicting id
for id in legacy_ids {
if store.capsules().get_snapshot(&owner, &id)?.is_some() {
eprintln!("durable capsule {id} already exists; resolve before migrating");
}
} Try / catch
if let Err(e) = migrate_native_capsules(home, store) {
if e.to_string().contains("conflicts with legacy native content") {
eprintln!("remove or align the conflicting durable capsule, then retry");
} else { return Err(e); }
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Same capsule id installed both durably (new system) and natively (legacy system) with different versions or builds; duplicate ids across development and release builds.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- durable capsule {id} failed byte-for-byte readback
- legacy capsule component path is not relative
- legacy capsule metadata has no WASM hash
- legacy capsule WIT path is not relative: {}
- legacy capsule directory {id} does not match manifest id {}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/6477f9b90e2de462.
Report an issue: GitHub.