spacejam/sled · critical

failed to fill whole buffer

Error message

failed to fill whole buffer

What it means

read_exact_at loops pwrite/pread-style reads until the buffer is filled; if the file ends before the requested bytes are available, it returns UnexpectedEof with this message. It means the caller expected data at a given offset that does not exist on disk.

Solutions

  1. Restore the database file from backup, as the expected bytes are missing
  2. Run filesystem checks (fsck) and confirm the file size matches expectations
  3. If a crash caused it, re-open and let the recovery/replay path rebuild, or re-import from an export
  4. Free disk space / fix storage issues that led to truncation before retrying
Defensive patterns

Strategy: try-catch

Validate before calling

// verify file size covers the offsets you expect to read
let len = file.metadata()?.len();
if offset + buf.len() as u64 > len { return Err(anyhow!("read beyond EOF: file truncated")); }

Try / catch

match Db::open(&path) {
    Ok(db) => db,
    Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => {
        restore_backup(&path)?; // data is missing on disk
        Db::open(&path)?
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Reading at an offset beyond the end of the file: truncated/corrupted database file, a crash that lost a write the in-memory state assumed was durable, or wrong offset bookkeeping.

Common situations: Recovering after a crash where file length metadata says data exists but writes were never flushed; disk full conditions truncating files; copying a database file partially.

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


AI-assisted analysis of spacejam/sled@e449d17111 (2026-09-12). Data as JSON: /api/errors/efd57418f1063535. Report an issue: GitHub.

Appendix: source

Thrown at src/heap.rs:465

    pub(super) fn read_exact_at(
        file: &fs::File,
        mut buf: &mut [u8],
        mut offset: u64,
    ) -> io::Result<()> {
        while !buf.is_empty() {
            match maybe!(file.seek_read(buf, offset)) {
                Ok(0) => break,
                Ok(n) => {
                    let tmp = buf;
                    buf = &mut tmp[n..];
                    offset += n as u64;
                }
                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
                Err(e) => return Err(annotate!(e)),
            }
        }
        if !buf.is_empty() {
            Err(annotate!(io::Error::new(
                io::ErrorKind::UnexpectedEof,
                "failed to fill whole buffer"
            )))
        } else {
            Ok(())
        }
    }

    pub(super) fn write_all_at(
        file: &fs::File,
        mut buf: &[u8],
        mut offset: u64,
    ) -> io::Result<()> {
        while !buf.is_empty() {
            match maybe!(file.seek_write(buf, offset)) {
                Ok(0) => {
                    return Err(annotate!(io::Error::new(
                        io::ErrorKind::WriteZero,

View on GitHub (pinned to e449d17111)