{"id":"4ba0df75f38e93ec","repo":"labstack/echo","slug":"response-writer-flushing-is-not-supported","errorCode":null,"errorMessage":"response writer flushing is not supported","messagePattern":"response writer flushing is not supported","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"middleware/body_dump.go","lineNumber":157,"sourceCode":"\t\t\tconfig.Handler(c, reqBody, resBuf.Bytes(), err)\n\n\t\t\treturn err\n\t\t}\n\t}, nil\n}\n\nfunc (w *bodyDumpResponseWriter) WriteHeader(code int) {\n\tw.ResponseWriter.WriteHeader(code)\n}\n\nfunc (w *bodyDumpResponseWriter) Write(b []byte) (int, error) {\n\treturn w.Writer.Write(b)\n}\n\nfunc (w *bodyDumpResponseWriter) Flush() {\n\terr := http.NewResponseController(w.ResponseWriter).Flush()\n\tif err != nil && errors.Is(err, http.ErrNotSupported) {\n\t\tpanic(errors.New(\"response writer flushing is not supported\"))\n\t}\n}\n\nfunc (w *bodyDumpResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {\n\treturn http.NewResponseController(w.ResponseWriter).Hijack()\n}\n\nfunc (w *bodyDumpResponseWriter) Unwrap() http.ResponseWriter {\n\treturn w.ResponseWriter\n}\n\nvar bodyDumpBufferPool = sync.Pool{\n\tNew: func() any {\n\t\treturn new(bytes.Buffer)\n\t},\n}\n\ntype limitedWriter struct {","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/labstack/echo/blob/05489dc1730161df26b72d1ae2a3ba6fb8178fc7/middleware/body_dump.go#L139-L175","documentation":"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()).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure the underlying ResponseWriter implements http.Flusher (httptest.ResponseRecorder does; wrap custom writers to forward Flush)","Skip BodyDump middleware for streaming endpoints using the Skipper function","Use a Recover middleware to catch the panic, though fixing the writer is the real solution"],"exampleFix":"// before — custom writer without Flush triggers panic\n// when handler calls c.Response().Flush()\n\n// after — implement Flush on your custom writer\ntype myWriter struct{ http.ResponseWriter }\nfunc (w *myWriter) Flush() {\n    if f, ok := w.ResponseWriter.(http.Flusher); ok { f.Flush() }\n}","handlingStrategy":"fallback","validationCode":null,"typeGuard":"// Check if the response writer supports flushing\nfunc canFlush(rw http.ResponseWriter) bool {\n    _, ok := rw.(http.Flusher)\n    return ok\n}","tryCatchPattern":"// Wrap with Recover middleware to catch the panic\ne.Use(middleware.Recover())\ne.Use(middleware.BodyDumpWithConfig(middleware.BodyDumpConfig{\n    Handler: dumpHandler,\n    Skipper: func(c echo.Context) bool {\n        // skip streaming endpoints that flush\n        return strings.HasPrefix(c.Path(), \"/stream\")\n    },\n}))","preventionTips":["Ensure custom ResponseWriter wrappers forward Flush() via http.Flusher","Use the Skipper to exclude streaming/SSE endpoints from BodyDump","Always pair BodyDump with Recover middleware as a safety net"],"tags":["middleware","body-dump","flush","streaming","panic"],"analyzedSha":"05489dc1730161df26b72d1ae2a3ba6fb8178fc7","analyzedAt":"2026-08-04T21:32:47.783Z","schemaVersion":2}