astrid-runtime/astrid · error
truncated Astrid volume record
Error message
truncated Astrid volume record
What it means
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.
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.
Defensive patterns
Strategy: validation
Validate before calling
// verify the file is large enough before attempting recovery
let len = file.metadata()?.len();
if footer_offset + FOOTER_BYTES > len {
return Err("volume file is truncated; restore before recovering");
} Try / catch
match recover_from_headers(&file) {
Err(e) if e.kind() == io::ErrorKind::UnexpectedEof => {
// truncated: restore full file from backup or recover only committed prefix
}
other => other?,
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- invalid Astrid volume record length at
- audit read failed
- destination.as_str()
- invalid interior Astrid volume record length at
- non-UTF-8 region name
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/53a9344c8a2af1fe.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-storage/src/volume/hosted/recover.rs:712
*cursor = end;
Ok(value)
}
fn read_array<const N: usize>(bytes: &[u8]) -> io::Result<[u8; N]> {
bytes
.try_into()
.map_err(|_| invalid_transition("invalid volume record integer"))
}
fn read_exact_at(file: &File, offset: u64, buffer: &mut [u8]) -> io::Result<()> {
let mut done = 0_usize;
while done < buffer.len() {
let read_offset = offset
.checked_add(done as u64)
.ok_or_else(|| io::Error::other("volume positional read offset overflow"))?;
let read = file_read_at(file, &mut buffer[done..], read_offset)?;
if read == 0 {
return Err(io::Error::new(
io::ErrorKind::UnexpectedEof,
"truncated Astrid volume record",
));
}
done = done
.checked_add(read)
.ok_or_else(|| io::Error::other("volume positional read length overflow"))?;
}
Ok(())
}
#[cfg(unix)]
fn file_read_at(file: &File, buffer: &mut [u8], offset: u64) -> io::Result<usize> {
use std::os::unix::fs::FileExt as _;
file.read_at(buffer, offset)
}
#[cfg(windows)]View on GitHub (pinned to affd8760f4)