{"record":{"id":"caf949d91fe80d3a","repo":"astrid-runtime/astrid","slug":"materialized-file-length-differs-from-its-descript","errorCode":null,"errorMessage":"materialized file length differs from its descriptor","messagePattern":"materialized file length differs from its descriptor","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/astrid-storage-chunker-evidence/src/sketch.rs","lineNumber":451,"sourceCode":"    }\n\n    fn record(&self, id: ObjectId) -> Result<&ObjectRecord> {\n        self.records\n            .binary_search_by_key(&id, |(object, _)| *object)\n            .ok()\n            .and_then(|index| self.records.get(index))\n            .map(|(_, record)| record)\n            .ok_or_else(|| anyhow::anyhow!(\"content DAG misses ordered chunk {id:?}\"))\n    }\n\n    fn materialize(&self) -> Result<Vec<u8>> {\n        let capacity = usize::try_from(self.logical_bytes)?;\n        let mut bytes = Vec::with_capacity(capacity);\n        for chunk in &self.chunks {\n            bytes.extend_from_slice(self.record(chunk.id)?.canonical_bytes());\n        }\n        if bytes.len() != capacity {\n            bail!(\"materialized file length differs from its descriptor\");\n        }\n        Ok(bytes)\n    }\n}\n\nfn collect_chunks(\n    id: ObjectId,\n    records: &BTreeMap<ObjectId, &ObjectRecord>,\n    offset: &mut u64,\n    chunks: &mut Vec<Chunk>,\n) -> Result<()> {\n    let record = records\n        .get(&id)\n        .copied()\n        .ok_or_else(|| anyhow::anyhow!(\"content DAG misses {id:?}\"))?;\n    match record.kind() {\n        ObjectKind::Chunk => {\n            let length = u64::try_from(record.canonical_bytes().len())?;","sourceCodeStart":433,"sourceCodeEnd":469,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-storage-chunker-evidence/src/sketch.rs#L433-L469","documentation":"materialize rebuilds the file bytes from canonical chunk records and cross-checks the resulting Vec's length against the descriptor's logical_bytes. A mismatch means materialized content differs from the declared size, signaling data loss or corruption in the chunk records.","triggerScenarios":"Calling materialize (used by delta_size) when the concatenated canonical chunk bytes total != self.logical_bytes — e.g. a chunk record's canonical bytes were re-encoded to a different length than originally counted.","commonSituations":"Chunk records transcoded or re-compressed between build and materialize; evidence files edited or truncated; mixing records from different measurement runs.","solutions":["Rebuild the version from source so chunk records and logical_bytes are consistent.","Verify each chunk record's canonical byte length matches its recorded length.","Re-download/regenerate the evidence artifacts if they were produced elsewhere."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"let canonical: usize = chunks.iter().map(|c| record(c.id).canonical_len()).sum();\nif canonical != logical_bytes as usize { return Err(anyhow!(\"canonical length drift\")); }","typeGuard":null,"tryCatchPattern":"match version.materialize() {\n    Err(e) if e.to_string().contains(\"differs from its descriptor\") => regenerate_evidence(),\n    other => other,\n}","preventionTips":["Never re-encode or recompress canonical chunk records between build and materialize","Validate record canonical lengths after loading persisted evidence","Regenerate evidence artifacts rather than repairing them by hand"],"tags":["integrity","materialization","invariant","chunking"],"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"}