astrid-runtime/astrid · error

present migration source has absent digest: {}

Error message

present migration source has absent digest: {}

What it means

For each ledger component, a present source must carry a real content digest; the sentinel value `"absent"` is reserved for sources that were verified not to exist. This error is thrown when a component claims `source.present == true` while its `source.digest` is still the `"absent"` sentinel — a self-contradictory ledger entry.

Source

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

                io::ErrorKind::InvalidData,
                format!(
                    "migration ledger contains duplicate component: {}",
                    component.name
                ),
            ));
        }
        if previous
            .as_ref()
            .is_some_and(|previous: &String| previous >= &component.name)
        {
            return Err(io::Error::new(
                io::ErrorKind::InvalidData,
                "migration ledger components are not canonically sorted",
            ));
        }
        previous = Some(component.name.clone());
        if component.source.present && component.source.digest == "absent" {
            return Err(io::Error::new(
                io::ErrorKind::InvalidData,
                format!(
                    "present migration source has absent digest: {}",
                    component.name
                ),
            ));
        }
        if !component.source.present && component.source.digest != "absent" {
            return Err(io::Error::new(
                io::ErrorKind::InvalidData,
                format!("absent migration source has a digest: {}", component.name),
            ));
        }
        if component.destination_proof.is_absent() && component.source.present {
            return Err(io::Error::new(
                io::ErrorKind::InvalidData,
                format!("invalid destination proof for component {}", component.name),
            ));

View on GitHub (pinned to affd8760f4)

Solutions

  1. Recompute the real source digest for the component's source path and write it into `source.digest`, keeping `present: true` only if the source actually exists.
  2. If the source truly does not exist, set `present: false` and `digest: "absent"` instead.
  3. Regenerate the component entry (and its destination proof) via the library's migration path rather than editing the JSON directly.
  4. Re-run the migration resume after the fix so all shape invariants are re-validated.

Example fix

// before
{"name": "principal:01H8X:home", "source": {"present": true, "digest": "absent"}}
// after
{"name": "principal:01H8X:home", "source": {"present": true, "digest": "sha256:9f2c..."}}
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight: present sources carry a real digest, absent sources use the sentinel
fn source_digest_consistent(c: &MigrationComponent) -> bool {
    if c.source.present { c.source.digest != "absent" } else { c.source.digest == "absent" }
}

Prevention

When it happens

Trigger: Calling `validate_ledger_shape` (via `write_ledger` or the decode/validate paths) on a `MigrationLedger` where a component has `source: {"present": true, "digest": "absent"}` — typically from hand-assembled JSON or a builder that set `present` without recomputing the digest.

Common situations: Hand-editing `present` from `false` to `true` without updating the digest; a script template filling in `present: true` while leaving the placeholder digest; partially applied migration steps where the digest update was lost.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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