{"record":{"id":"dffbfd29942a8e23","repo":"astrid-runtime/astrid","slug":"vectored-frame-append-made-no-progress","errorCode":null,"errorMessage":"vectored frame append made no progress","messagePattern":"vectored frame append made no progress","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/astrid-storage/src/engine/durable/format/prepared.rs","lineNumber":115,"sourceCode":"fn write_all_vectored<W: Write + ?Sized>(\n    writer: &mut W,\n    slices: &mut [IoSlice<'_>],\n) -> Result<(), DurableError> {\n    let mut remaining = slices;\n    while !remaining.is_empty() {\n        let written = loop {\n            match writer.write_vectored(remaining) {\n                Ok(written) => break written,\n                Err(source) if source.kind() == io::ErrorKind::Interrupted => {},\n                Err(source) => {\n                    return Err(io_error(\"append prepared durable frame batch\", source));\n                },\n            }\n        };\n        if written == 0 {\n            return Err(io_error(\n                \"append prepared durable frame batch\",\n                io::Error::new(\n                    io::ErrorKind::WriteZero,\n                    \"vectored frame append made no progress\",\n                ),\n            ));\n        }\n        IoSlice::advance_slices(&mut remaining, written);\n    }\n    Ok(())\n}\n\n#[cfg(test)]\nmod tests {\n    use std::fs::File;\n    use std::io::{Read, Seek, SeekFrom};\n\n    use super::*;\n    use crate::engine::durable::append_frames;\n","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-storage/src/engine/durable/format/prepared.rs#L97-L133","documentation":"This WriteZero error is raised by write_all_vectored when a vectored (scatter/gather) write of prepared durable frames reports 0 bytes written. A vectored write that returns Ok(0) means no progress was made, which would otherwise cause an infinite retry loop in the caller. The library treats zero-progress appends as an I/O fault and aborts the frame-batch append.","triggerScenarios":"Calling append_prepared_frames (which routes through write_all_vectored) when the underlying writer accepts zero bytes, e.g. writing to a closed/full pipe, a file at a hard resource limit, or a writer whose write_vectored implementation spuriously returns Ok(0). vectored_append_retries_interrupted_and_short_writes surfaces it after retries are exhausted.","commonSituations":"Disk full or quota exceeded on the journal device; running inside a container with a frozen filesystem; a custom/wrapped writer with a buggy write_vectored that returns 0 instead of WouldBlock; EINTR-style interruptions the retry loop could not recover from.","solutions":["Check disk space, quota, and inode availability on the storage device holding the durable log","Retry the append operation; transient zero-progress writes often clear once the device recovers","If wrapping the writer, fix write_vectored to return Err(WouldBlock) or a nonzero count instead of Ok(0)","Verify the target file handle is still open and valid; reopen the journal if the handle went stale"],"exampleFix":"// before\nwriter.write_vectored(&bufs)?; // returns Ok(0) silently\n// after\nlet n = writer.write_vectored(&bufs)?;\nif n == 0 {\n    return Err(io::Error::new(io::ErrorKind::WriteZero, \"no progress\"));\n}","handlingStrategy":"try-catch","validationCode":"// before appending\nlet avail = fs4::available_space(log_path)?;\nif avail < required_batch_bytes { return Err(\"insufficient disk space\".into()); }","typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if e.kind() == io::ErrorKind::WriteZero => {\n        // check disk space / handle validity, then retry append\n        eprintln!(\"vectored append made no progress: {e}\");\n    }\n    ...\n}","preventionTips":["Monitor free disk space and quotas on the journal volume","Do not wrap the journal writer with custom write_vectored implementations that can return Ok(0)","Keep retry/backoff logic around appends in the caller","Alert on WriteZero occurrences as device-health signals"],"tags":["io","storage","vectored-write"],"backgroundTag":"file-write-failed","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}