astrid-runtime/astrid · error
invalid capsule authority migration receipt: {}
Error message
invalid capsule authority migration receipt: {} What it means
`collect_destination_proofs` reads a stored DestinationProof from the migrations ledger and validates its shape: it must start with the `verified-capsule-authority-v1:` prefix and embed the current authority source digest. If either check fails, the receipt is rejected as invalid. This is fail-closed validation to ensure migration receipts genuinely attest to the same capsule authority source.
Source
Thrown at crates/astrid-kernel/src/legacy_migration_barrier/ledger.rs:95
"verified-system-env-v1:source-digest={}:markers=blake3:{}",
host_source.digest,
blake3::hash(&receipt).to_hex()
))?
} else {
DestinationProof::absent()
},
);
}
if let Some(authority_source) = sources.get("system:capsule-authority") {
let proof = if authority_source.present {
let path = home.migrations_dir().join(CAPSULE_AUTHORITY_RECEIPT_NAME);
let proof = DestinationProof::from_stored(
fs::read_to_string(&path).map_err(io::Error::other)?,
)?;
if !proof.starts_with("verified-capsule-authority-v1:")
|| !proof.contains(&format!("source-digest={}", authority_source.digest))
{
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!(
"invalid capsule authority migration receipt: {}",
path.display()
),
));
}
proof
} else {
DestinationProof::absent()
};
proofs.insert("system:capsule-authority".to_owned(), proof);
}
let audit = store.system_control_kv("audit").map_err(storage_io)?;
let audit_proof = audit
.get("audit:migrations:legacy-principal-home-v1")
.awaitView on GitHub (pinned to affd8760f4)
Solutions
- Inspect the receipt file named in the message; confirm the `verified-capsule-authority-v1:` prefix and `source-digest=...` field.
- If the authority source legitimately changed, re-run the full migration (e.g. migrate_legacy_layout / initialize_fresh_layout) so receipts are regenerated for the new digest.
- If receipts are corrupt or from an unknown source, restore them from a trusted backup or re-migrate from scratch; never hand-edit receipts.
Example fix
// before: hand-edited receipt missing the digest verified-capsule-authority-v1:manual-ok // after: delete and regenerate via migration $ rm <migrations-dir>/<receipt>.json && astrid migrate
Defensive patterns
Strategy: try-catch
Validate before calling
let raw = std::fs::read_to_string(&receipt_path)?;
let digest_ok = raw.starts_with("verified-capsule-authority-v1:")
&& raw.contains(&format!("source-digest={digest}"));
if !digest_ok { eprintln!("receipt stale or corrupt; re-migrate"); } Try / catch
match migrate_legacy_layout(...) {
Err(e) if e.to_string().contains("invalid capsule authority migration receipt") => {
eprintln!("receipts do not match current authority; re-run full migration");
}
r => r?,
} Prevention
- Never hand-edit receipt files under migrations_dir.
- Back up the whole migrations directory atomically (ledger + receipts together).
- Re-migrate from scratch after any change that alters the capsule authority source digest.
When it happens
Trigger: The receipt file at the given path was hand-edited, truncated, written by an older/other version, or its embedded source-digest no longer matches the current authority_source.digest (e.g. the authority source changed after receipts were recorded).
Common situations: Manual tampering with receipts in migrations_dir; migrating after upgrading the code so the authority digest changed while old receipts persist; restoring a partial backup of the migrations directory.
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
- principal migration component has no ordinary-home receipt:
- destination receipt changed for migration component {}
- required system migration receipt is missing: {}
- live principal migration receipt is missing: {}
- durable capsule {id} has unsafe WIT metadata path {relative}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/7cb35c65d8cdafc8.
Report an issue: GitHub.