astrid-runtime/astrid · error
legacy capsule {id} changed before retirement
Error message
legacy capsule {id} changed before retirement What it means
Just before retiring the legacy directory, migration rebuilds the canonical archive from the legacy files and compares it to the archive that was published durably. If they differ, the legacy capsule mutated during migration (after its contents were verified and copied), so retirement is refused to avoid deleting changed data.
Source
Thrown at crates/astrid-capsule-install/src/storage/migration.rs:194
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 {
bail!("legacy capsule {id} metadata changed before retirement");
}
if read_installed_authority_bytes(home, &target)?.as_deref()
!= Some(source_authority_bytes.as_slice())
{
bail!("legacy capsule {id} authority changed before retirement");
}
astrid_core::platform_fs::verify_no_redirects(&target)
.with_context(|| format!("verify legacy capsule {id} retirement boundary"))?;
astrid_core::dirs::retire_legacy_source_tree(&target)
.with_context(|| format!("retire migrated legacy capsule {id}"))?;
retire_legacy_authority_receipt(home, &target, &source_authority_bytes)
.with_context(|| format!("retire migrated legacy capsule {id} authority"))?;
report
.retired_authorities
.push(LegacyCapsuleAuthorityReceipt {View on GitHub (pinned to affd8760f4)
Solutions
- Ensure the capsule is not running and nothing writes into the legacy directory, then re-run migration
- Exclude the legacy path from sync tools during migration
- Revert or commit any local changes to the legacy capsule, then migrate the stable version
Example fix
// before migrate while my-capsule binary is running // after pkill my-capsule; migrate_all_native_capsules(store)
Defensive patterns
Strategy: validation
Validate before calling
// ensure nothing can write into the legacy tree during migration
if process_running(&capsule_executable) { return Err("stop the capsule before migrating"); }
let h1 = hash_tree(&legacy_dir);
std::thread::sleep(Duration::from_secs(1));
if hash_tree(&legacy_dir) != h1 { return Err("legacy tree is changing"); } Try / catch
if let Err(e) = migrate_native_capsules(home, store) {
if e.to_string().contains("changed before retirement") {
eprintln!("legacy capsule mutated mid-migration; quiesce it and retry");
} else { return Err(e); }
} Prevention
- Stop capsule processes before migrating their directories
- Pause cloud-sync/indexing on the legacy directory during migration
- Do not edit installed capsules while migration runs
- Migrate once at a stable point (after install/upgrade, before launch)
When it happens
Trigger: Files in the legacy capsule directory changed between the initial canonical_legacy_archive call and the final re-check — e.g. a running capsule process rewrote its files, or a user/sync tool edited them mid-migration.
Common situations: The migrated capsule's executable was still running and wrote state; cloud-sync touched the directory; developer edited files during migration.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- legacy capsule {id} metadata changed before retirement
- layout migration source changed type: {}
- legacy capsule component path is not relative
- legacy capsule metadata has no WASM hash
- legacy capsule WIT path is not relative: {}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/7e33faefe5b60432.
Report an issue: GitHub.