{"record":{"id":"5dcd77cbeb5f874a","repo":"tokio-rs/tokio","slug":"failed-to-write-the-buffered-data","errorCode":null,"errorMessage":"failed to write the buffered data","messagePattern":"failed to write the buffered data","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"tokio/src/io/util/buf_writer.rs","lineNumber":66,"sourceCode":"    /// Creates a new `BufWriter` with the specified buffer capacity.\n    pub fn with_capacity(cap: usize, inner: W) -> Self {\n        Self {\n            inner,\n            buf: Vec::with_capacity(cap),\n            written: 0,\n            seek_state: SeekState::Init,\n        }\n    }\n\n    fn flush_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {\n        let mut me = self.project();\n\n        let len = me.buf.len();\n        let mut ret = Ok(());\n        while *me.written < len {\n            match ready!(me.inner.as_mut().poll_write(cx, &me.buf[*me.written..])) {\n                Ok(0) => {\n                    ret = Err(io::Error::new(\n                        io::ErrorKind::WriteZero,\n                        \"failed to write the buffered data\",\n                    ));\n                    break;\n                }\n                Ok(n) => *me.written += n,\n                Err(e) => {\n                    ret = Err(e);\n                    break;\n                }\n            }\n        }\n        if *me.written > 0 {\n            me.buf.drain(..*me.written);\n        }\n        *me.written = 0;\n        Poll::Ready(ret)\n    }","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/tokio-rs/tokio/blob/625954f365727668cb02d04172b34f1149637728/tokio/src/io/util/buf_writer.rs#L48-L84","documentation":"Thrown by BufWriter's flush_buf when the wrapped writer's poll_write returns Ok(0) — i.e. it accepted zero bytes of buffered output. Tokio treats a successful-but-empty write as a hard failure because flushing cannot make progress, so the buffered data is effectively undeliverable. The error carries io::ErrorKind::WriteZero so callers can distinguish it from transient backpressure.","triggerScenarios":"Calling .flush()/.shutdown() (or letting the internal buffer fill and auto-flush) on a tokio::io::BufWriter wrapping a sink that has been closed, half-closed, or that always returns 0 from poll_write. Directly observed when the downstream connection drops mid-write or a custom AsyncWrite returns Ok(0) erroneously.","commonSituations":"Writing to a TCP/Unix stream after the peer has closed its read side; a broken pipe whose SIGPIPE was suppressed; a custom AsyncWrite with a buggy poll_write; writing past EOF on a special file. Frequently surfaces in proxy/streaming code after the remote disconnects.","solutions":["Verify the underlying writer is still connected before flushing (e.g. check a connection flag or preceding read returning 0).","Handle io::ErrorKind::WriteZero explicitly in the caller and treat it as a closed-sink condition rather than a generic error.","If using a custom AsyncWrite, ensure poll_write never returns Ok(0) when the buffer is non-empty — return Poll::Pending instead and register the waker.","Flush more frequently so the failure surfaces closer to its cause, or avoid wrapping an already-closed writer."],"exampleFix":"// before\nlet mut w = BufWriter::new(stream);\nw.write_all(data).await?;\nw.flush().await?; // panics-on-err if peer closed\n\n// after\nmatch w.flush().await {\n    Ok(()) => {},\n    Err(e) if e.kind() == io::ErrorKind::WriteZero => {\n        // downstream closed; stop writing\n        break;\n    }\n    Err(e) => return Err(e),\n}","handlingStrategy":"try-catch","validationCode":"// Before flushing, probe the writer with a 0-byte write or track a 'closed' flag\n// set when a prior write returned Err(BrokenPipe) / read returned 0.\nif writer.is_closed() { return Ok(()); }\nwriter.flush().await?;","typeGuard":"fn is_write_zero(e: &io::Error) -> bool {\n    e.kind() == io::ErrorKind::WriteZero\n}","tryCatchPattern":"match writer.flush().await {\n    Ok(()) => {},\n    Err(e) if e.kind() == io::ErrorKind::WriteZero => {\n        // downstream sink closed; stop the write loop\n        break;\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Track the downstream connection state and stop flushing once a peer close is observed.","When implementing a custom AsyncWrite, never return Ok(0) on a non-empty write — return Pending.","Flush in smaller increments so closures surface near their cause.","Don't wrap a writer you've already half-closed."],"tags":["io","buf-writer","write-zero","tokio"],"backgroundTag":null,"analyzedSha":"625954f365727668cb02d04172b34f1149637728","analyzedAt":"2026-08-11T17:46:45.378Z","contentChangedAt":"2026-08-11T17:46:45.378Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}