astrid-runtime/astrid · error

Astrid volume record checksum mismatch

Error message

Astrid volume record checksum mismatch

What it means

Each volume record's BLAKE3 checksum (keyed with "astrid volume record v1" over the sequence, name, logical offset, payload length, name bytes, and payload) is verified when the payload is read back. The recomputed hash does not match the checksum stored in the header, so the record's bytes are corrupt or the header fields were altered.

Solutions

  1. Restore the volume from backup; checksummed records that fail cannot be trusted.
  2. Confirm the file was written by the same format version/key derivation ('astrid volume record v1'); version mismatches fail every record.
  3. If every record fails, suspect the wrong file or a format change rather than random corruption — check the volume's format/version markers.
  4. Run disk/filesystem integrity checks if failures are localized or recurring.
Defensive patterns

Strategy: try-catch

Try / catch

match recover_from_headers(&file) {
    Err(e) if e.to_string().contains("checksum mismatch") => {
        // record untrustworthy: restore from backup; if ALL records fail, suspect format/version mismatch
    }
    other => other?,
}

Prevention

When it happens

Trigger: verify_record_checksum, called from read_record_payload during recovery, reads a record (name + payload + header fields) whose recomputed BLAKE3 digest differs from header.checksum — corrupt payload bytes, wrong key/format version, or misinterpreted header fields.

Common situations: Bit rot or bad sectors flipping payload bytes on disk; recovery run against a file written by a different volume format/key version ('astrid volume record v1' mismatch); torn writes without fs-level protection; manual editing or copying of the volume file.

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/362a4afbed2d5d27. Report an issue: GitHub.

Appendix: source

Thrown at crates/astrid-storage/src/volume/hosted/recover.rs:464

    read_exact_at(file, header.payload_offset, &mut payload)?;
    verify_record_checksum(header, &payload)?;
    Ok(Some(payload))
}

fn verify_record_checksum(header: &RecordHeader, payload: &[u8]) -> io::Result<()> {
    let mut hasher = blake3::Hasher::new_derive_key("astrid volume record v1");
    hasher.update(&header.sequence.to_le_bytes());
    hasher.update(&[header.operation as u8]);
    let name = header.name.as_str().as_bytes();
    let name_len =
        u16::try_from(name.len()).map_err(|_| invalid_transition("region name too long"))?;
    hasher.update(&name_len.to_le_bytes());
    hasher.update(&header.logical_offset.to_le_bytes());
    hasher.update(&header.payload_len.to_le_bytes());
    hasher.update(name);
    hasher.update(payload);
    if hasher.finalize().as_bytes() != &header.checksum {
        return Err(io::Error::new(
            io::ErrorKind::InvalidData,
            "Astrid volume record checksum mismatch",
        ));
    }
    Ok(())
}

fn read_commit(
    file: &File,
    offset: u64,
    durable_len: u64,
    sequence: u64,
) -> io::Result<Option<(RecordHeader, Vec<u8>)>> {
    let Some(header) = read_header(file, offset, durable_len)? else {
        return Ok(None);
    };
    if header.operation != Operation::Commit
        || header.name.as_str() != COMMIT_REGION

View on GitHub (pinned to affd8760f4)