{"record":{"id":"53a9344c8a2af1fe","repo":"astrid-runtime/astrid","slug":"truncated-astrid-volume-record","errorCode":null,"errorMessage":"truncated Astrid volume record","messagePattern":"truncated Astrid volume record","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-storage/src/volume/hosted/recover.rs","lineNumber":712,"sourceCode":"    *cursor = end;\n    Ok(value)\n}\n\nfn read_array<const N: usize>(bytes: &[u8]) -> io::Result<[u8; N]> {\n    bytes\n        .try_into()\n        .map_err(|_| invalid_transition(\"invalid volume record integer\"))\n}\n\nfn read_exact_at(file: &File, offset: u64, buffer: &mut [u8]) -> io::Result<()> {\n    let mut done = 0_usize;\n    while done < buffer.len() {\n        let read_offset = offset\n            .checked_add(done as u64)\n            .ok_or_else(|| io::Error::other(\"volume positional read offset overflow\"))?;\n        let read = file_read_at(file, &mut buffer[done..], read_offset)?;\n        if read == 0 {\n            return Err(io::Error::new(\n                io::ErrorKind::UnexpectedEof,\n                \"truncated Astrid volume record\",\n            ));\n        }\n        done = done\n            .checked_add(read)\n            .ok_or_else(|| io::Error::other(\"volume positional read length overflow\"))?;\n    }\n    Ok(())\n}\n\n#[cfg(unix)]\nfn file_read_at(file: &File, buffer: &mut [u8], offset: u64) -> io::Result<usize> {\n    use std::os::unix::fs::FileExt as _;\n    file.read_at(buffer, offset)\n}\n\n#[cfg(windows)]","sourceCodeStart":694,"sourceCodeEnd":730,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-storage/src/volume/hosted/recover.rs#L694-L730","documentation":"The positional read helper read_exact_at loops until it fills the caller's buffer from a fixed file offset. When the underlying read returns 0 bytes before the buffer is full (premature EOF), the requested record bytes do not exist in the file, so it raises UnexpectedEof 'truncated Astrid volume record'. All volume parsing (headers, payloads, footers) funnels through this helper, so any parse that runs past the file's end produces this error.","triggerScenarios":"Any of read_header, read_record_payload, recover_footer_at, recover_from_headers, has_physically_valid_record_after, or read_header_without_tail_scan asks for N bytes at an offset where fewer than N bytes exist — a header length field points beyond the file end, the footer offset is past EOF, or the file was truncated mid-record.","commonSituations":"The volume file was copied incompletely or truncated (disk full, interrupted rsync/cp); a crashed writer left a partial final record; recovery is pointed at the wrong (shorter) file; a corrupt length field makes the parser read past the real end.","solutions":["Check the file size against the expected volume size; if it's short, re-copy or restore the complete file.","Restore the volume from backup or the last committed footer/commit point.","Discard the torn tail record if the region tolerates losing the final write, then re-open the volume.","Verify the recovery is reading the intended file path and not a stale or partial copy."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// verify the file is large enough before attempting recovery\nlet len = file.metadata()?.len();\nif footer_offset + FOOTER_BYTES > len {\n    return Err(\"volume file is truncated; restore before recovering\");\n}","typeGuard":null,"tryCatchPattern":"match recover_from_headers(&file) {\n    Err(e) if e.kind() == io::ErrorKind::UnexpectedEof => {\n        // truncated: restore full file from backup or recover only committed prefix\n    }\n    other => other?,\n}","preventionTips":["After copying volumes, compare byte length against the source before use.","Ensure the writer flushes/fsyncs complete records; avoid hard kills during writes.","Monitor disk-full conditions on the volume host.","Use filesystem-level snapshots instead of raw copies for backups."],"tags":["storage","io","truncation","unexpected-eof"],"backgroundTag":"file-read-failed","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"}