{"record":{"id":"9a4439f261abf3b9","repo":"tokio-rs/tokio","slug":"failed-to-write-frame-to-transport","errorCode":null,"errorMessage":"failed to write frame to transport","messagePattern":"failed to write frame to transport","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"tokio-util/src/codec/framed_impl.rs","lineNumber":290,"sourceCode":"        pinned\n            .codec\n            .encode(item, &mut pinned.state.borrow_mut().buffer)?;\n        Ok(())\n    }\n\n    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {\n        use crate::util::poll_write_buf;\n        trace!(\"flushing framed transport\");\n        let mut pinned = self.project();\n\n        while !pinned.state.borrow_mut().buffer.is_empty() {\n            let WriteFrame { buffer, .. } = pinned.state.borrow_mut();\n            trace!(remaining = buffer.len(), \"writing;\");\n\n            let n = ready!(poll_write_buf(pinned.inner.as_mut(), cx, buffer))?;\n\n            if n == 0 {\n                return Poll::Ready(Err(io::Error::new(\n                    io::ErrorKind::WriteZero,\n                    \"failed to \\\n                     write frame to transport\",\n                )\n                .into()));\n            }\n        }\n\n        // Try flushing the underlying IO\n        ready!(pinned.inner.poll_flush(cx))?;\n\n        trace!(\"framed transport flushed\");\n        Poll::Ready(Ok(()))\n    }\n\n    fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {\n        ready!(self.as_mut().poll_flush(cx))?;\n        ready!(self.project().inner.poll_shutdown(cx))?;","sourceCodeStart":272,"sourceCodeEnd":308,"githubUrl":"https://github.com/tokio-rs/tokio/blob/625954f365727668cb02d04172b34f1149637728/tokio-util/src/codec/framed_impl.rs#L272-L308","documentation":"Runtime error from the `Sink` `poll_flush` of `Framed`/`FramedWrite` (framed_impl.rs). While the output buffer is non-empty, `poll_write_buf` returned `Ok(0)` — the underlying writer accepted zero bytes. Tokio treats this as a `WriteZero` failure: the transport cannot accept the frame.","triggerScenarios":"The underlying `AsyncWrite` returned `0` from `write` without an error during a `Framed` sink flush — e.g. writing to a half-closed socket, a closed pipe, or a TLS session that has shut down the write side.","commonSituations":"Peer closed the connection while you were still sending (broken pipe / connection reset reported as a zero write); writing after `poll_close`/`poll_shutdown`; half-open TCP socket; a custom `AsyncWrite` that returns 0 spuriously.","solutions":["Treat the error as terminal for that connection: drop it and reconnect.","Confirm you are not writing after shutting down the transport.","Inspect `io::Error::kind()` (`WriteZero`) to distinguish a dead transport from transient backpressure.","For custom `AsyncWrite` impls, never return `Ok(0)` unless genuinely EOF — return `Poll::Pending` instead."],"exampleFix":"// before: ignoring sink errors\nframed.send(item).await.unwrap();\n\n// after: treat flush failure as a closed transport\nif let Err(e) = framed.send(item).await {\n    if e.kind() == io::ErrorKind::WriteZero {\n        // transport is closed: reconnect or shut down this peer\n        reconnect().await;\n    } else {\n        return Err(e.into());\n    }\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"fn is_transport_dead(e: &io::Error) -> bool {\n    matches!(e.kind(), io::ErrorKind::WriteZero | io::ErrorKind::BrokenPipe | io::ErrorKind::ConnectionReset)\n}","tryCatchPattern":"if let Err(e) = framed.send(item).await {\n    if is_transport_dead(&e) { reconnect().await; continue; }\n    return Err(e.into());\n}","preventionTips":["Never write after `poll_close`/`poll_shutdown` on the transport.","Custom `AsyncWrite` impls should return `Poll::Pending`, not `Ok(0)`, when they cannot currently accept bytes.","Model a zero-write as a terminal connection error in your reconnect logic."],"tags":["rust","tokio","tokio-util","codec","sink","network","runtime"],"backgroundTag":null,"analyzedSha":"625954f365727668cb02d04172b34f1149637728","analyzedAt":"2026-08-11T17:46:45.378Z","contentChangedAt":"2026-08-11T17:46:45.378Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}