labstack/echo · critical
response writer flushing is not supported
Error message
response writer flushing is not supported
What it means
Panicked at request time by delayedStatusWriter.Flush (used in the error-handler path) when the underlying http.ResponseWriter does not support the http.Flusher interface (detected via http.NewResponseController returning http.ErrNotSupported). Flushing is needed when middleware or handlers call c.Response().Flush() while the delayed writer is buffering the status code; if the real writer cannot flush, there is no safe fallback, so Echo panics.
Source
Thrown at response.go:163
w.committed = true
w.ResponseWriter.WriteHeader(statusCode)
}
func (w *delayedStatusWriter) Write(data []byte) (int, error) {
if !w.committed {
w.committed = true
if w.status == 0 {
w.status = http.StatusOK
}
w.ResponseWriter.WriteHeader(w.status)
}
return w.ResponseWriter.Write(data)
}
func (w *delayedStatusWriter) Flush() {
err := http.NewResponseController(w.ResponseWriter).Flush()
if err != nil && errors.Is(err, http.ErrNotSupported) {
panic(errors.New("response writer flushing is not supported"))
}
}
func (w *delayedStatusWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
return http.NewResponseController(w.ResponseWriter).Hijack()
}
func (w *delayedStatusWriter) Unwrap() http.ResponseWriter {
return w.ResponseWriter
}
// headResponseWriter captures the response that a GET handler would produce for a
// rewritten HEAD request, suppresses the body, and preserves response metadata.
//
// The writer buffers status until the downstream handler returns, so it
// can compute a Content-Length value from the number of body bytes that would have
// been written by the GET handler. If the handler already sets Content-Length
// explicitly, that value is preserved.View on GitHub (pinned to 05489dc173)
Solutions
- Ensure the underlying http.ResponseWriter (or any wrapper in its Unwrap chain) implements http.Flusher (Flush()).
- In tests, prefer httptest.NewRecorder() which supports Flusher, or wrap your custom writer to forward Flush to a real implementation.
- Avoid calling c.Response().Flush() from middleware that may run inside the error-handling path unless you know the writer supports it.
- If using a custom server adapter, document/verify that its ResponseWriter implements http.Flusher.
Example fix
// before: custom writer has no Flush
type memWriter struct{ header http.Header; body bytes.Buffer }
// after: implement http.Flusher
type memWriter struct{ header http.Header; body bytes.Buffer }
func (w *memWriter) Flush() {} // satisfy http.Flusher
func (w *memWriter) Unwrap() http.ResponseWriter { return nil } Defensive patterns
Strategy: validation
Validate before calling
func supportsFlush(rw http.ResponseWriter) bool {
// walk the Unwrap chain the same way ResponseController does
for {
if _, ok := rw.(http.Flusher); ok { return true }
if u, ok := rw.(interface{ Unwrap() http.ResponseWriter }); ok {
rw = u.Unwrap()
continue
}
return false
}
} Try / catch
// recover at the server boundary if a non-flushable writer is unavoidable
defer func() {
if r := recover(); r != nil {
c.Error(echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("%v", r)))
}
}() Prevention
- Make sure the underlying http.ResponseWriter (or a wrapper in its Unwrap chain) implements http.Flusher.
- In tests, use httptest.NewRecorder() (supports Flush) or implement Flush() on custom writers.
- Avoid calling c.Response().Flush() from middleware that may run inside the error-handling path on non-flushable writers.
- Verify any custom server adapter's ResponseWriter implements http.Flusher before deploying.
When it happens
Trigger: An error occurs in the handler chain (delayedStatusWriter is engaged) and then something calls Flush on a writer whose chain does not implement http.Flusher — e.g., httptest.ResponseRecorder (which does implement Flush in newer Go, but custom recorders may not) or a bespoke in-memory writer.
Common situations: Tests using a custom ResponseWriter that omits Flush; or a deployment behind a non-standard server adapter whose writer lacks Flusher support, combined with the error-handling path that engages the delayed writer.
Related errors
- echo: response writer %T does not support flushing (http.Flu
- ResponseWriter does not implement 'Unwrap() http.ResponseWri
- route not found
- route not found by method and path
- route not found by method
AI-assisted analysis of labstack/echo@05489dc173 (2026-08-04).
Data as JSON: /data/errors/59621e3234433801.json.
Report an issue: GitHub.