astrid-runtime/astrid · error
absent migration source has a digest: {}
Error message
absent migration source has a digest: {} What it means
validate_ledger_shape enforces that every migration ledger component's source presence flag is consistent with its digest. A component whose source is not present must carry the literal digest "absent"; any other digest is a self-contradictory record. This is an InvalidData io::Error raised during ledger admission before any migration state is written.
Source
Thrown at crates/astrid-kernel/src/legacy_migration_barrier/ledger.rs:642
.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),
));
}
if component.name == "system:cow" {
let expected = format!("source-digest={}", component.source.digest);
if !component
.destination_proof
.starts_with("verified-discard-v1:")
|| !component.destination_proof.contains(&expected)
|| !component
.destination_proofView on GitHub (pinned to affd8760f4)
Solutions
- Set source.digest to the literal string "absent" whenever source.present is false
- If the source actually exists, set source.present = true and keep the real digest
- Regenerate the ledger entry with the library's own writer instead of constructing it by hand
Example fix
// before
MigrationSource { present: false, digest: "blake3:abc123", .. }
// after
MigrationSource { present: false, digest: "absent", .. } Defensive patterns
Strategy: validation
Validate before calling
fn source_absent_digest_ok(c: &MigrationComponent) -> bool {
c.source.present || c.source.digest == "absent"
}
// validate all components before calling write_ledger
let ok = ledger.components.iter().all(source_absent_digest_ok); Type guard
fn has_consistent_source(c: &MigrationComponent) -> bool {
if c.source.present { c.source.digest != "absent" } else { c.source.digest == "absent" }
} Try / catch
match write_ledger(&ledger) {
Err(e) if e.kind() == io::ErrorKind::InvalidData && e.to_string().contains("absent migration source has a digest") => {
// fix source.present/digest pairing and retry
}
other => other?,
} Prevention
- Always construct MigrationSource through a helper that keeps present and digest in sync
- Never hand-edit ledger JSON; regenerate it via the library's writer
- Add a unit test asserting absent sources use the "absent" sentinel
When it happens
Trigger: Calling write_ledger (directly or via reject_incomplete_layout_v2, retire_post_barrier_sources, or resume_existing_layout, or the ledger-shape tests) with a MigrationLedger containing a component where source.present == false but source.digest is set to a real digest value instead of "absent".
Common situations: Hand-edited or programmatically generated ledger JSON where an author zeroes out the source but forgets to reset the digest; migrating ledgers between schema versions that changed the sentinel convention; copying a component entry and clearing present without clearing digest.
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
- InvalidData
- principal migration component has no ordinary-home receipt:
- required system migration receipt is missing: {}
- live principal migration receipt is missing: {}
- unknown migration component name: {name}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/2abb5ca174e3b9a3.
Report an issue: GitHub.