EpicGames/lore · error · io::Error
file refused further writes
Error message
file refused further writes
What it means
write_all_at could not complete the requested write: the underlying write backend (IOCP) reported zero bytes written at some point mid-loop, so the file accepted no further data. The library surfaces this as ErrorKind::WriteZero rather than silently returning a short write, guaranteeing the caller that the full buffer was either written or the call fails.
Solutions
- Check disk space / quota on the target volume and free space or move the file.
- Verify the file was not truncated or replaced by another process; reopen and retry the whole write.
- Confirm the file is opened for writing at the requested offset and the volume supports files that large.
- Retry with a smaller write or use plain filesystem paths rather than special devices.
Example fix
// before
file.write_all_at(&buf, offset).await?; // panics/unhandled WriteZero on full disk
// after
match file.write_all_at(&buf, offset).await {
Ok(()) => {}
Err(e) if e.kind() == std::io::ErrorKind::WriteZero => {
ensure_disk_space(&path)?;
file.write_all_at(&buf, offset).await?;
}
Err(e) => return Err(e),
} Defensive patterns
Strategy: try-catch
Validate before calling
// Rust
let free = fs2::available_space(&path)?;
if free < buf.len() as u64 { return Err(std::io::Error::new(std::io::ErrorKind::StorageFull, "no space")); } Try / catch
// Rust
match file.write_all_at(&buf, offset).await {
Ok(()) => {}
Err(e) if e.kind() == std::io::ErrorKind::WriteZero => { /* free space / reopen / retry once */ }
Err(e) => return Err(e.into()),
} Prevention
- Check free disk space before large writes
- Avoid writing to files other processes may truncate; use locking
- Write to temp file + rename for durability
- Handle ErrorKind::WriteZero explicitly in all write paths
When it happens
Trigger: Calling write_all_at on a file whose writer end is effectively closed or whose size cannot grow — e.g. writing past a size-capped file, a full/quota-exhausted volume, or a file opened in a mode that truncates or rejects further writes — and the overlapped write operation completes successfully with 0 bytes.
Common situations: Disk full or quota exceeded mid-write; the file was truncated/deleted by another process between writes; writing to a special file (pipe, named pipe) that closed; filesystem size limits hit at the offset being written.
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
- file refused further writes
- file refused further writes
- file ended before the requested read length
- file shrank while reading
- file refused further writes
AI-assisted analysis of EpicGames/lore@074eb0b0d1 (2026-09-13).
Data as JSON: /api/errors/0bdb72663d3ac142.
Report an issue: GitHub.
Appendix: source
Thrown at lore-io/src/iocp.rs:447
/// Writes all `len` bytes. See [`Self::read_exact_at`] for why each pass is its own
/// submission.
pub(crate) async fn write_all_at<B: StableBuf>(
&self,
file: Arc<File>,
buffer: B,
len: usize,
offset: u64,
) -> std::io::Result<B> {
let mut buffer = buffer;
let mut done = 0;
while done < len {
let (payload, result) = self
.write(&file, buffer, done, len - done, offset + done as u64)
.await;
buffer = payload.buffer;
match result? {
0 => {
return Err(std::io::Error::new(
std::io::ErrorKind::WriteZero,
"file refused further writes",
));
}
written => done += written,
}
}
Ok(buffer)
}
/// Scatters a read across the segments, one segment per operation.
///
/// Windows has no positional scatter/gather call for an ordinary handle — `ReadFileScatter`
/// takes page-aligned, sector-sized segments only — so a segment list becomes a sequence of
/// operations however it is issued. Issuing them here rather than forwarding to
/// [`PsyncDriver`] is what keeps them off the pool: the psync backend walks the segments with
/// blocking positional calls inside one dispatch, holding a thread for the whole list.
///View on GitHub (pinned to 074eb0b0d1)