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")
        .await

View on GitHub (pinned to affd8760f4)

Solutions

  1. Inspect the receipt file named in the message; confirm the `verified-capsule-authority-v1:` prefix and `source-digest=...` field.
  2. 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.
  3. 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

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


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