astrid-runtime/astrid · error
legacy capsule {id} metadata changed before retirement
Error message
legacy capsule {id} metadata changed before retirement What it means
As a final pre-retirement check, migration re-reads meta.json and compares it byte-for-byte to the metadata that was published durably. A difference means the legacy metadata changed during migration, so the legacy directory is not retired and the error is raised to protect the mutated data.
Source
Thrown at crates/astrid-capsule-install/src/storage/migration.rs:197
};
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 {
uid,
capsule_id: id.to_owned(),
authority_digest: blake3::hash(&package.authority).to_hex().to_string(),View on GitHub (pinned to affd8760f4)
Solutions
- Stop any process that could write meta.json, then re-run migration
- Serialize migrations so only one runs at a time
- Restore meta.json to the version matching the published package, or re-migrate from scratch
Example fix
// before migrate while capsule service updates meta.json // after systemctl --user stop my-capsule; migrate_all_native_capsules(store)
Defensive patterns
Strategy: validation
Validate before calling
// verify meta.json stability before migrating
let before = std::fs::read(capsule_dir.join("meta.json")).map_err(|e| e.to_string())?;
std::thread::sleep(Duration::from_secs(1));
if std::fs::read(capsule_dir.join("meta.json")).map_err(|e| e.to_string())? != before {
return Err("meta.json is being rewritten".into());
} Try / catch
if let Err(e) = migrate_native_capsules(home, store) {
if e.to_string().contains("metadata changed before retirement") {
eprintln!("meta.json changed mid-migration; stop the writer and retry");
} else { return Err(e); }
} Prevention
- Stop capsule services that update meta.json before migrating
- Run only one migration at a time
- Exclude legacy paths from sync/backup tools during migration
- Take a snapshot of the legacy tree before migration for safe rollback
When it happens
Trigger: meta.json was rewritten between its initial read and the final retirement check — e.g. the capsule process updated its own metadata, an installer touched it, or a sync tool restored a different copy.
Common situations: Running capsule writing version/state updates to meta.json mid-migration; backup/restore tools rewriting metadata; concurrent second migration attempt.
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} changed before retirement
- legacy capsule metadata has no WASM hash
- legacy capsule metadata version differs for {id}
- layout migration source changed type: {}
- WASM capsule has no BLAKE3 hash in meta.json
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/b23d384e43340f6d.
Report an issue: GitHub.