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

  1. Remove the conflicting durable capsule (or the legacy one) so only one source of truth remains
  2. Rebuild the legacy capsule to match the durable content, or vice versa
  3. Migrate under a corrected unique id if two genuinely different capsules collide
  4. 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

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


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/6477f9b90e2de462. Report an issue: GitHub.