astrid-runtime/astrid · error

live principal migration receipt is missing: {}

Error message

live principal migration receipt is missing: {}

What it means

For principal components that currently have a live projection in the destination directory, `validate_existing_proofs` requires a receipt — unless the component is absent both at source and per the recorded (absent) proof. If a live principal component is missing its receipt despite being present at source or not recorded as absent, this error is thrown. Deleted historical UIDs are intentionally exempt (no live projection), so the failure indicates ledger/receipts inconsistency for a component that should have one.

Source

Thrown at crates/astrid-kernel/src/legacy_migration_barrier/ledger.rs:441

            continue;
        }
        if component.name.starts_with("system:") {
            return Err(io::Error::new(
                io::ErrorKind::InvalidData,
                format!(
                    "required system migration receipt is missing: {}",
                    component.name
                ),
            ));
        }
        // A current UID's immutable receipt/marker cannot silently disappear.
        // Deleted historical UIDs are intentionally allowed to have no live
        // projection, and an originally absent component remains absent when
        // its ledger proof was explicitly recorded as such.
        if is_live_principal_component(&component.name, directory)
            && (component.source.present || !component.destination_proof.is_absent())
        {
            return Err(io::Error::new(
                io::ErrorKind::InvalidData,
                format!(
                    "live principal migration receipt is missing: {}",
                    component.name
                ),
            ));
        }
        if let Some(uid) = principal_component_uid(&component.name)
            && !directory.contains_uid(uid)
            && component.name.ends_with(":home")
        {
            let receipt = home
                .migrations_dir()
                .join(format!("principal-home-{uid}.json"));
            let actual = destination_file_proof(&receipt)?;
            if actual != component.destination_proof {
                return Err(io::Error::new(
                    io::ErrorKind::InvalidData,

View on GitHub (pinned to affd8760f4)

Solutions

  1. Re-run resume_existing_layout / migration to generate a receipt for the now-live principal component.
  2. If the component is genuinely absent, ensure the ledger records the proof as explicitly absent so the exemption applies.
  3. Audit cleanup jobs so they do not delete receipts from migrations_dir while components remain live.

Example fix

// before: cleanup script deleted receipts but component is live on disk
$ astrid migrate  # regenerate receipts for live components
// after: exclude migrations_dir from cleanup cron
Defensive patterns

Strategy: try-catch

Validate before calling

if is_live_principal_component(&name, &dir) && source_present && !receipt_exists(&name) {
    eprintln!("live principal component {} lacks a receipt", name);
}

Try / catch

match resume_existing_layout(...) {
    Err(e) if e.to_string().contains("live principal migration receipt is missing") => {
        eprintln!("re-run migration to issue receipts for live principal components");
    }
    r => r?,
}

Prevention

When it happens

Trigger: validate_existing_proofs finds is_live_principal_component(name, directory) true while component.source.present is true or component.destination_proof is not the explicit absent marker, and no receipt exists for it.

Common situations: The user was recreated (same UID) after migrating, so the component is live again but no new receipt exists; receipts were deleted by cleanup scripts; the ledger was restored from a snapshot taken before the component existed.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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