labstack/echo · critical

response writer flushing is not supported

Error message

response writer flushing is not supported

What it means

Panicked (not returned) by bodyDumpResponseWriter.Flush when the underlying http.ResponseWriter does not support flushing, as reported by http.NewResponseController(...).Flush() returning http.ErrNotSupported. The BodyDump wrapper proxies Flush to the real writer; if the real writer cannot flush, the middleware panics because flushing was explicitly requested (e.g. by a handler calling c.Response().Flush()).

Source

Thrown at middleware/body_dump.go:157

			config.Handler(c, reqBody, resBuf.Bytes(), err)

			return err
		}
	}, nil
}

func (w *bodyDumpResponseWriter) WriteHeader(code int) {
	w.ResponseWriter.WriteHeader(code)
}

func (w *bodyDumpResponseWriter) Write(b []byte) (int, error) {
	return w.Writer.Write(b)
}

func (w *bodyDumpResponseWriter) 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 *bodyDumpResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
	return http.NewResponseController(w.ResponseWriter).Hijack()
}

func (w *bodyDumpResponseWriter) Unwrap() http.ResponseWriter {
	return w.ResponseWriter
}

var bodyDumpBufferPool = sync.Pool{
	New: func() any {
		return new(bytes.Buffer)
	},
}

type limitedWriter struct {

View on GitHub (pinned to 05489dc173)

Solutions

  1. Ensure the underlying ResponseWriter implements http.Flusher (httptest.ResponseRecorder does; wrap custom writers to forward Flush)
  2. Skip BodyDump middleware for streaming endpoints using the Skipper function
  3. Use a Recover middleware to catch the panic, though fixing the writer is the real solution

Example fix

// before — custom writer without Flush triggers panic
// when handler calls c.Response().Flush()

// after — implement Flush on your custom writer
type myWriter struct{ http.ResponseWriter }
func (w *myWriter) Flush() {
    if f, ok := w.ResponseWriter.(http.Flusher); ok { f.Flush() }
}
Defensive patterns

Strategy: fallback

Type guard

// Check if the response writer supports flushing
func canFlush(rw http.ResponseWriter) bool {
    _, ok := rw.(http.Flusher)
    return ok
}

Try / catch

// Wrap with Recover middleware to catch the panic
e.Use(middleware.Recover())
e.Use(middleware.BodyDumpWithConfig(middleware.BodyDumpConfig{
    Handler: dumpHandler,
    Skipper: func(c echo.Context) bool {
        // skip streaming endpoints that flush
        return strings.HasPrefix(c.Path(), "/stream")
    },
}))

Prevention

When it happens

Trigger: Using BodyDump middleware with a handler that calls c.Response().Flush() (SSE, streaming, chunked responses) when the underlying ResponseWriter does not implement http.Flusher. Happens in test setups with httptest.ResponseRecorder (which implements Flush) but can fail with custom writers or certain server configurations.

Common situations: Streaming/SSE handlers combined with BodyDump middleware in a test environment using a non-flushable mock ResponseWriter. Custom ResponseWriter wrappers that don't forward Flush.

Related errors


AI-assisted analysis of labstack/echo@05489dc173 (2026-08-04). Data as JSON: /data/errors/4ba0df75f38e93ec.json. Report an issue: GitHub.