databendlabs/databend · error
writev returned zero bytes
Error message
writev returned zero bytes
What it means
`writev_all` writes multiple I/O slices with `pwritev` at a given offset, looping until all slices are consumed. A `pwritev` returning 0 means no bytes were written and no progress is possible, so it aborts with `ErrorKind::WriteZero` to avoid an infinite loop. Reached via `flush_if_full`/`flush_inner` when flushing buffered DMA writes.
Solutions
- Check free disk space and quotas on the target device (`df -h`, project quotas).
- Confirm the mount supports O_DIRECT + pwritev correctly (ext4/xfs are safe; some network/FUSE filesystems are not).
- Ensure no concurrent truncation of the data file by other processes.
- Retry the write; if deterministic, fall back to non-direct I/O or re-align buffers.
Defensive patterns
Strategy: try-catch
Validate before calling
// check disk headroom before flushing
fn has_headroom(dir: &Path, need: u64) -> std::io::Result<bool> {
Ok(fs2::available_space(dir)? > need)
} Try / catch
match writer.flush() {
Err(e) if e.kind() == std::io::ErrorKind::WriteZero => handle_flush_failure(e), // disk full / fs issue
other => other,
} Prevention
- Monitor free space on the data volume
- Use filesystems with solid pwritev + O_DIRECT support
- Avoid external truncation of in-use files
When it happens
Trigger: During buffer flush, `rustix::io::pwritev` returns `Ok(0)` — no bytes accepted by the kernel for the aligned offset, e.g. disk full at EOF, filesystem oddity, or an invalid fd state.
Common situations: Disk/quota exhaustion, writes to a file on a filesystem with broken vectored-I/O support, file truncated concurrently by another process, O_DIRECT incompatibility with the buffer alignment.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- write returned zero bytes
- Expected to have bytes
- Expected to have insensitive bytes
- Expected to ignore a byte
- Fst data is corrupted
AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11).
Data as JSON: /api/errors/b961fa731819968d.
Report an issue: GitHub.
Appendix: source
Thrown at src/common/base/src/base/dma.rs:717
}
pub fn flush_and_close(&mut self, mut file: SyncDmaFile) -> io::Result<usize> {
self.flush_inner(&mut file, true)?;
Ok(file.length())
}
pub fn flush(&mut self, file: &mut SyncDmaFile) -> io::Result<()> {
self.flush_inner(file, false)
}
}
fn writev_all(fd: impl AsFd, mut slices: &mut [IoSlice<'_>], offset: usize) -> io::Result<usize> {
let mut written = 0;
while !slices.is_empty() {
match rustix::io::pwritev(fd.as_fd(), slices, (offset + written) as _) {
Ok(0) => {
return Err(io::Error::new(
io::ErrorKind::WriteZero,
"writev returned zero bytes",
));
}
Ok(n) => {
written += n;
IoSlice::advance_slices(&mut slices, n);
}
Err(err) => {
if err.kind() == io::ErrorKind::Interrupted {
continue;
}
return Err(err.into());
}
};
}
Ok(written)View on GitHub (pinned to 288d84d76e)