astrid-runtime/astrid · critical

ordered chunk traversal did not reconstruct the declared…

Error message

ordered chunk traversal did not reconstruct the declared file length

What it means

from_built reconstructs a file by traversing its chunks in order and asserts the summed chunk bytes equal the descriptor's declared logical length. A mismatch means the chunk graph is inconsistent with the file descriptor — corruption or an internal bug.

Solutions

  1. Regenerate the evidence from the source corpus so descriptors and chunk records are rebuilt together.
  2. Verify no records were dropped during serialization/deserialization.
  3. Validate the descriptor's logical_bytes against the actual file size before building.
Defensive patterns

Strategy: try-catch

Validate before calling

let actual: u64 = records.values().map(|r| r.len() as u64).sum();
if actual != descriptor.logical_bytes() { return Err(anyhow!("descriptor length mismatch")); }

Try / catch

match Version::from_built(descriptor, records) {
    Err(e) if e.to_string().contains("reconstruct the declared file length") => rebuild_from_source(),
    other => other,
}

Prevention

When it happens

Trigger: Constructing Version/State via from_built when collect_chunks accumulates an offset that differs from descriptor.logical_bytes() — e.g. records missing from the BTreeMap, truncated chunk data, or a descriptor written before the last chunks were built.

Common situations: Partially written evidence artifacts; descriptors from an older format version; hand-assembled chunk records in tests.

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/4917a5bc2346042e. Report an issue: GitHub.

Appendix: source

Thrown at crates/astrid-storage-chunker-evidence/src/sketch.rs:389

impl Version {
    fn build(bytes: &[u8]) -> Result<Self> {
        let built = build_content(&Blake3ObjectIdentityV1, ChunkingProfile::ASTRID_V1, bytes)
            .context("build production content DAG for sketch evidence")?;
        Self::from_built(built)
    }

    fn from_built(built: BuiltContent) -> Result<Self> {
        let descriptor = built.descriptor();
        let records = built.into_records();
        let by_id = records
            .iter()
            .map(|(id, record)| (*id, record))
            .collect::<BTreeMap<_, _>>();
        let mut chunks = Vec::new();
        let mut offset = 0_u64;
        collect_chunks(descriptor.file(), &by_id, &mut offset, &mut chunks)?;
        if offset != descriptor.logical_bytes() {
            bail!("ordered chunk traversal did not reconstruct the declared file length");
        }
        Ok(Self {
            file: descriptor.file(),
            logical_bytes: descriptor.logical_bytes(),
            records,
            chunks,
        })
    }

    fn sketch(&self, descriptor: BottomKSketchDescriptor) -> Result<MaterializedSketch> {
        let scanned_bytes = self.records.iter().try_fold(0_u64, |total, (_, record)| {
            checked_add(total, record.retained_bytes()?, "sketch scan bytes")
        })?;
        let descriptor_record = descriptor.record()?;
        let started = Instant::now();
        let outputs = build_bottom_k_sketch(
            &Blake3ObjectIdentityV1,
            descriptor,

View on GitHub (pinned to affd8760f4)