{"record":{"id":"f3942be82ac4ea18","repo":"oven-sh/bun","slug":"writefailed-f3942b","errorCode":"WriteFailed","errorMessage":"WriteFailed","messagePattern":"WriteFailed","errorType":"error_code","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/http/error.rs","lineNumber":8,"sourceCode":"#[allow(non_camel_case_types)]\n#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]\npub enum Error {\n    #[error(\"CompressionFailed\")]\n    CompressionFailed,\n    #[error(\"Aborted\")]\n    Aborted,\n    #[error(\"WriteFailed\")]\n    WriteFailed,\n    #[error(\"HTTP2RefusedStream\")]\n    HTTP2RefusedStream,\n    #[error(\"HTTP2ContentLengthMismatch\")]\n    HTTP2ContentLengthMismatch,\n    #[error(\"HTTP2FrameSizeError\")]\n    HTTP2FrameSizeError,\n    #[error(\"HTTP2ProtocolError\")]\n    HTTP2ProtocolError,\n    #[error(\"HTTP2FlowControlError\")]\n    HTTP2FlowControlError,\n    #[error(\"HTTP2EnhanceYourCalm\")]\n    HTTP2EnhanceYourCalm,\n    #[error(\"HTTP2HeaderListTooLarge\")]\n    HTTP2HeaderListTooLarge,\n    #[error(\"HTTP2StreamReset\")]\n    HTTP2StreamReset,\n    #[error(\"HTTP2GoAway\")]","sourceCodeStart":1,"sourceCodeEnd":26,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/src/http/error.rs#L1-L26","documentation":"Writing to the socket failed inside the HTTP client — the h2 session sets it when flushing the write buffer or sending frames hits an I/O error (src/http/h2_client/ClientSession.rs:782, :820, :917; src/http/lib.rs:1480). In practice the peer closed the connection while Bun was still writing (EPIPE/ECONNRESET), so the request fails mid-body. The same variant name is reused by other crates' enums for file-write failures, but in bun_http::Error it is specifically a socket/stream write failure.","triggerScenarios":"POSTing a request body to a server that already closed the connection (keep-alive race, server-side timeout, LB idle cutoff), writing to an h2 session after GOAWAY processing began, or a peer resetting the TCP connection mid-write.","commonSituations":"Keep-alive connections reused after the server's idle timeout (common with nginx keepalive_timeout shorter than the client pool's); proxies closing slow uploads; servers with aggressive request timeouts (e.g. 30s body limit) killing long uploads.","solutions":["Retry the request — the connection is dead, but a fresh one usually succeeds; keep the body buffered so it is reusable.","Send the request sooner after acquiring a pooled connection, or enable smaller keep-alive windows on your side so stale sockets are pruned.","For long uploads, raise the server/proxy timeout (proxy_read_timeout, LB idle timeout) above your worst-case upload duration.","If it happens consistently against one endpoint, capture `tcpdump`/server logs to see which side closes first — a server-side 408/499 preceding the close means the app is too slow, not the network."],"exampleFix":"// before\nconst res = await fetch(url, { method: 'POST', body }); // fails once with WriteFailed after idle reuse\n// after: retry once on write failure (idempotent request)\nasync function post(url, body) {\n  for (let i = 0; ; i++) {\n    try { return await fetch(url, { method: 'POST', body }); }\n    catch (e) { if (i >= 1 || !/WriteFailed|EPIPE|ECONNRESET/i.test(String(e.message))) throw e; }\n  }\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":"function isWriteFailure(err) {\n  const s = String(err?.message ?? err);\n  return /WriteFailed|EPIPE|ECONNRESET|broken pipe/i.test(s);\n}","tryCatchPattern":"async function fetchRetryWrite(url, init, tries = 2) {\n  for (let i = 0; ; i++) {\n    try { return await fetch(url, init); }\n    catch (err) {\n      if (i >= tries || !isWriteFailure(err)) throw err;\n      await Bun.sleep(50 * (i + 1)); // new connection on retry\n    }\n  }\n}","preventionTips":["Keep request bodies buffered (strings/ArrayBuffer) so retries can resend","Only retry idempotent or safely repeatable requests after write failures","Tune client keep-alive idle below the server's keepalive_timeout to avoid stale sockets"],"tags":["http","network","socket","fetch","broken-pipe"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}