EpicGames/lore · error · io::Error

file refused further writes

Error message

file refused further writes

What it means

`IoFile::write_all_vectored_at` loops issuing vectored writes until all requested bytes are written. A zero-byte write from `write_vectored_at_raw` means the file (or underlying storage) accepted no bytes at all — this maps to io::ErrorKind::WriteZero, mirroring std's WriteZero on zero-progress writes, and aborts so the caller never silently loses data.

Solutions

  1. Check disk space/quota and the validity of the file handle, then retry the operation with a freshly opened file.
  2. Treat WriteZero as fatal for data integrity: do not retry blindly in a loop without diagnosing why zero bytes were written.
  3. Log the offset and remaining buffer state at failure so the partially-written region can be repaired or rewritten.

Example fix

// before
file.write_all_vectored_at(buffers, offset).await?; // may return WriteZero
// after
match file.write_all_vectored_at(buffers, offset).await {
    Err(e) if e.kind() == std::io::ErrorKind::WriteZero => {
        // reopen file / check disk space, then rewrite from `offset`
    }
    r => r?,
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Rust: cheap pre-checks before large vectored writes
fn preflight_write(disk_free: u64, to_write: usize, offset: u64) -> Result<(), &'static str> {
    if (to_write as u64) > disk_free.saturating_sub(offset) {
        return Err("insufficient disk space for vectored write");
    }
    Ok(())
}

Try / catch

// Rust
match file.write_all_vectored_at(buffers, offset).await {
    Err(e) if e.kind() == std::io::ErrorKind::WriteZero => {
        // reopen the file / check disk space, do NOT blind-retry
        let fresh = driver.open(path, true).await?;
        fresh.write_all_vectored_at(buffers, offset).await?;
    }
    r => r?,
}

Prevention

When it happens

Trigger: Calling `write_all_vectored_at` when the underlying write makes zero progress — e.g. a device/full filesystem reporting no bytes written, a closed or invalid file handle in the driver, or an I/O error surfaced as a 0-length write from the completion backend.

Common situations: Writing to a disk that is full or a quota-exceeded volume; a file that was closed/unlinked underneath the driver (stale Arc handle); fault-injection tests where the backend returns zero-progress completions.

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


AI-assisted analysis of EpicGames/lore@074eb0b0d1 (2026-09-13). Data as JSON: /api/errors/7aca593ca80b4dd7. Report an issue: GitHub.

Appendix: source

Thrown at lore-io/src/file.rs:240

    /// Writes the combined contents of all segments at `offset`, gathering
    /// directly from the segments with no intermediate buffer.
    pub async fn write_all_vectored_at<B: StableBufList>(
        &self,
        buffers: B,
        offset: u64,
    ) -> std::io::Result<B> {
        let mut buffers = buffers;
        let total: usize = buffers.byte_segments().map(|segment| segment.len()).sum();
        let mut done = 0;
        while done < total {
            let (returned, written) = self
                .driver
                .write_vectored_at_raw(Arc::clone(&self.file), buffers, done, offset + done as u64)
                .await?;
            buffers = returned;
            if written == 0 {
                return Err(std::io::Error::new(
                    std::io::ErrorKind::WriteZero,
                    "file refused further writes",
                ));
            }
            done += written;
        }
        Ok(buffers)
    }

    /// Syncs file data (not necessarily metadata) to disk.
    pub async fn sync_data(&self) -> std::io::Result<()> {
        self.driver.sync_raw(Arc::clone(&self.file), true).await
    }

    /// Syncs file data and metadata to disk.
    pub async fn sync_all(&self) -> std::io::Result<()> {
        self.driver.sync_raw(Arc::clone(&self.file), false).await
    }

View on GitHub (pinned to 074eb0b0d1)