{"record":{"id":"cb663d0f9f0a9580","repo":"EpicGames/lore","slug":"file-refused-further-writes-uring","errorCode":null,"errorMessage":"file refused further writes","messagePattern":"file refused further writes","errorType":"exception","errorClass":"io::Error (WriteZero)","httpStatus":null,"severity":"error","filePath":"lore-io/src/uring.rs","lineNumber":405,"sourceCode":"        len: usize,\n        offset: u64,\n    ) -> std::io::Result<B> {\n        let mut buffer = buffer;\n        let mut done = 0;\n        while done < len {\n            let entry = write_entry(\n                &file,\n                buffer.as_ref(),\n                done,\n                len - done,\n                offset + done as u64,\n            );\n            let (payload, result) = self.submit(entry, payload(buffer, &file))?.await;\n            buffer = payload.buffer;\n            match interpret(result)? {\n                Progress::Interrupted => {}\n                Progress::Bytes(0) => {\n                    return Err(std::io::Error::new(\n                        std::io::ErrorKind::WriteZero,\n                        \"file refused further writes\",\n                    ));\n                }\n                Progress::Bytes(written) => done += written,\n            }\n        }\n        Ok(buffer)\n    }\n\n    /// Scatters one read across the segments, returning how many bytes it filled.\n    ///\n    /// The iovec array is rebuilt for every pass because it travels into the op entry with the\n    /// segments, and a pass that made partial progress needs a different array anyway: the skip\n    /// moves and the leading segments drop out.\n    pub(crate) async fn read_vectored_at<B: StableBufListMut>(\n        &self,\n        file: Arc<File>,","sourceCodeStart":387,"sourceCodeEnd":423,"githubUrl":"https://github.com/EpicGames/lore/blob/074eb0b0d1194c997d7cf28b55519e3e197b3e23/lore-io/src/uring.rs#L387-L423","documentation":"The io_uring write_all_at loop treats a completed write of 0 bytes as \"the file refused further writes\" and fails with ErrorKind::WriteZero. This preserves all-or-nothing semantics: either the whole buffer is written or the caller gets an error, never a silent partial write.","triggerScenarios":"Calling write_all_at when an io_uring write completes with 0 bytes: full volume/quota, file truncated concurrently, write at an offset the filesystem cannot extend, or a special-file target that stopped accepting data.","commonSituations":"Disk-full during a large async write; ENOSPC surfacing as a zero-length completion; concurrent truncation by another task/process; container disk limits hit mid-write.","solutions":["Free disk space / raise quota, then retry the write from a known offset.","Reopen the file and restart the write; a 0-byte write mid-loop means prior bytes may be durable, so rewrite the whole buffer if idempotence matters.","Stat available space before large writes and stream in chunks with ENOSPC handling.","Ensure the file is opened with write/append permissions and the offset is within a supportable range."],"exampleFix":"// before\nfile.write_all_at(&data, offset).await?; // WriteZero on full disk\n// after\nif free_bytes(&path)? < data.len() as u64 {\n    return Err(std::io::Error::new(std::io::ErrorKind::StorageFull, \"volume full\"));\n}\nfile.write_all_at(&data, offset).await?;","handlingStrategy":"try-catch","validationCode":"// Rust\nif fs2::available_space(&path)? < data.len() as u64 {\n    return Err(std::io::Error::new(std::io::ErrorKind::StorageFull, \"volume full before async write\"));\n}","typeGuard":null,"tryCatchPattern":"// Rust\nmatch file.write_all_at(&data, offset).await {\n    Ok(()) => {}\n    Err(e) if e.kind() == std::io::ErrorKind::WriteZero => { /* ENOSPC: free space, reopen, rewrite whole buffer */ }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Check volume free space before large async writes","Treat WriteZero as disk-full, not a transient glitch","Avoid concurrent truncation; coordinate with locks or atomic replace","Keep writes idempotent so a failed write_all_at can be safely retried in full"],"tags":["io","io-uring","async","write"],"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"}