{"record":{"id":"4917a5bc2346042e","repo":"astrid-runtime/astrid","slug":"ordered-chunk-traversal-did-not-reconstruct-the-de","errorCode":null,"errorMessage":"ordered chunk traversal did not reconstruct the declared file length","messagePattern":"ordered chunk traversal did not reconstruct the declared file length","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/astrid-storage-chunker-evidence/src/sketch.rs","lineNumber":389,"sourceCode":"impl Version {\n    fn build(bytes: &[u8]) -> Result<Self> {\n        let built = build_content(&Blake3ObjectIdentityV1, ChunkingProfile::ASTRID_V1, bytes)\n            .context(\"build production content DAG for sketch evidence\")?;\n        Self::from_built(built)\n    }\n\n    fn from_built(built: BuiltContent) -> Result<Self> {\n        let descriptor = built.descriptor();\n        let records = built.into_records();\n        let by_id = records\n            .iter()\n            .map(|(id, record)| (*id, record))\n            .collect::<BTreeMap<_, _>>();\n        let mut chunks = Vec::new();\n        let mut offset = 0_u64;\n        collect_chunks(descriptor.file(), &by_id, &mut offset, &mut chunks)?;\n        if offset != descriptor.logical_bytes() {\n            bail!(\"ordered chunk traversal did not reconstruct the declared file length\");\n        }\n        Ok(Self {\n            file: descriptor.file(),\n            logical_bytes: descriptor.logical_bytes(),\n            records,\n            chunks,\n        })\n    }\n\n    fn sketch(&self, descriptor: BottomKSketchDescriptor) -> Result<MaterializedSketch> {\n        let scanned_bytes = self.records.iter().try_fold(0_u64, |total, (_, record)| {\n            checked_add(total, record.retained_bytes()?, \"sketch scan bytes\")\n        })?;\n        let descriptor_record = descriptor.record()?;\n        let started = Instant::now();\n        let outputs = build_bottom_k_sketch(\n            &Blake3ObjectIdentityV1,\n            descriptor,","sourceCodeStart":371,"sourceCodeEnd":407,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-storage-chunker-evidence/src/sketch.rs#L371-L407","documentation":"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.","triggerScenarios":"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.","commonSituations":"Partially written evidence artifacts; descriptors from an older format version; hand-assembled chunk records in tests.","solutions":["Regenerate the evidence from the source corpus so descriptors and chunk records are rebuilt together.","Verify no records were dropped during serialization/deserialization.","Validate the descriptor's logical_bytes against the actual file size before building."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"let actual: u64 = records.values().map(|r| r.len() as u64).sum();\nif actual != descriptor.logical_bytes() { return Err(anyhow!(\"descriptor length mismatch\")); }","typeGuard":null,"tryCatchPattern":"match Version::from_built(descriptor, records) {\n    Err(e) if e.to_string().contains(\"reconstruct the declared file length\") => rebuild_from_source(),\n    other => other,\n}","preventionTips":["Always build descriptors and chunk records together in one pass","Validate evidence artifacts on load (sum of chunk lengths vs logical_bytes)","Avoid mixing records across format versions"],"tags":["integrity","chunking","invariant","reconstruction"],"backgroundTag":"checksum-mismatch","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}