gofiber/fiber · error
failed to write response body to writer
Error message
failed to write response body to writer: %w
What it means
Response.Save, given an io.Writer, copies the body stream into it with io.Copy. This wraps a failure of that copy: a read error from the response body or a write error from the supplied writer (closed pipe, buffer overflow, custom Writer erroring).
Solutions
- Inspect the wrapped cause to tell reader-side (network) from writer-side (your Writer) failures.
- Ensure the Writer remains open and writable for the entire Save call; do not close it beforehand.
- For long streams, set appropriate timeouts and propagate context cancellation cleanly.
Defensive patterns
Strategy: try-catch
Type guard
func isWriteCloser(v any) (io.Writer, bool) {
w, ok := v.(io.Writer)
return w, ok
} Try / catch
if _, err := io.Copy(w, r.BodyStream()); err != nil {
if errors.Is(err, io.ErrClosedPipe) || errors.Is(err, syscall.EPIPE) {
// writer closed before body finished; abort cleanly
}
return err
} Prevention
- Keep the supplied Writer open and writable for the whole Save call.
- Distinguish reader-side (network) from writer-side (your Writer) errors via the wrapped cause.
- Propagate context cancellation to avoid writing into a dead sink.
When it happens
Trigger: Passing a *pipe.Writer whose read end is closed; a bytes.Buffer that hits allocation limits; an HTTP response writer that has already been flushed/closed; a custom Writer returning an error; the upstream connection resetting mid-stream.
Common situations: Writing into an http.ResponseWriter after the client disconnected; piping into a process whose stdin closed; a streaming consumer that errors on a specific payload; network drops mid-copy.
Related errors
- failed to write response body to file
- failed to check directory
- failed to create directory
- failed to create file
- only file paths and io.Writer are supported
AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11).
Data as JSON: /api/errors/ce61eb421f2c2b6c.
Report an issue: GitHub.
Appendix: source
Thrown at client/response.go:220
// Create and write to file
outFile, err := os.Create(file)
if err != nil {
return fmt.Errorf("failed to create file: %w", err)
}
defer func() { _ = outFile.Close() }() //nolint:errcheck // not needed
// Use BodyStream() which handles both streaming and non-streaming cases
if _, err = io.Copy(outFile, r.BodyStream()); err != nil {
return fmt.Errorf("failed to write response body to file: %w", err)
}
return nil
case io.Writer:
// Use BodyStream() which handles both streaming and non-streaming cases
if _, err := io.Copy(p, r.BodyStream()); err != nil {
return fmt.Errorf("failed to write response body to writer: %w", err)
}
// Close the writer if it implements io.WriteCloser
if pc, ok := p.(io.WriteCloser); ok {
_ = pc.Close() //nolint:errcheck // not needed
}
return nil
default:
return ErrNotSupportSaveMethod
}
}
// Reset clears the Response object, making it ready for reuse.
func (r *Response) Reset() {
r.client = nil
r.request = nil
r.respondedHost = resetOriginBuf(r.respondedHost)View on GitHub (pinned to a105acad6c)