{"record":{"id":"7aca593ca80b4dd7","repo":"EpicGames/lore","slug":"file-refused-further-writes","errorCode":null,"errorMessage":"file refused further writes","messagePattern":"file refused further writes","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"lore-io/src/file.rs","lineNumber":240,"sourceCode":"\n    /// Writes the combined contents of all segments at `offset`, gathering\n    /// directly from the segments with no intermediate buffer.\n    pub async fn write_all_vectored_at<B: StableBufList>(\n        &self,\n        buffers: B,\n        offset: u64,\n    ) -> std::io::Result<B> {\n        let mut buffers = buffers;\n        let total: usize = buffers.byte_segments().map(|segment| segment.len()).sum();\n        let mut done = 0;\n        while done < total {\n            let (returned, written) = self\n                .driver\n                .write_vectored_at_raw(Arc::clone(&self.file), buffers, done, offset + done as u64)\n                .await?;\n            buffers = returned;\n            if written == 0 {\n                return Err(std::io::Error::new(\n                    std::io::ErrorKind::WriteZero,\n                    \"file refused further writes\",\n                ));\n            }\n            done += written;\n        }\n        Ok(buffers)\n    }\n\n    /// Syncs file data (not necessarily metadata) to disk.\n    pub async fn sync_data(&self) -> std::io::Result<()> {\n        self.driver.sync_raw(Arc::clone(&self.file), true).await\n    }\n\n    /// Syncs file data and metadata to disk.\n    pub async fn sync_all(&self) -> std::io::Result<()> {\n        self.driver.sync_raw(Arc::clone(&self.file), false).await\n    }","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/EpicGames/lore/blob/074eb0b0d1194c997d7cf28b55519e3e197b3e23/lore-io/src/file.rs#L222-L258","documentation":"`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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check disk space/quota and the validity of the file handle, then retry the operation with a freshly opened file.","Treat WriteZero as fatal for data integrity: do not retry blindly in a loop without diagnosing why zero bytes were written.","Log the offset and remaining buffer state at failure so the partially-written region can be repaired or rewritten."],"exampleFix":"// before\nfile.write_all_vectored_at(buffers, offset).await?; // may return WriteZero\n// after\nmatch file.write_all_vectored_at(buffers, offset).await {\n    Err(e) if e.kind() == std::io::ErrorKind::WriteZero => {\n        // reopen file / check disk space, then rewrite from `offset`\n    }\n    r => r?,\n}","handlingStrategy":"try-catch","validationCode":"// Rust: cheap pre-checks before large vectored writes\nfn preflight_write(disk_free: u64, to_write: usize, offset: u64) -> Result<(), &'static str> {\n    if (to_write as u64) > disk_free.saturating_sub(offset) {\n        return Err(\"insufficient disk space for vectored write\");\n    }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"// Rust\nmatch file.write_all_vectored_at(buffers, offset).await {\n    Err(e) if e.kind() == std::io::ErrorKind::WriteZero => {\n        // reopen the file / check disk space, do NOT blind-retry\n        let fresh = driver.open(path, true).await?;\n        fresh.write_all_vectored_at(buffers, offset).await?;\n    }\n    r => r?,\n}","preventionTips":["Monitor free disk space and quota on volumes used by the store.","Reopen files after external processes may have closed or unlinked them.","Log offset + buffer lengths on write failure to enable targeted repair."],"tags":["io","write","async","file"],"backgroundTag":"file-write-failed","analyzedSha":"074eb0b0d1194c997d7cf28b55519e3e197b3e23","analyzedAt":"2026-09-13T09:00:57.509Z","contentChangedAt":"2026-09-13T09:00:57.509Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}