{"id":"656b86b07a0b3b2b","repo":"labstack/echo","slug":"echo-response-writer-t-does-not-support-flushing","errorCode":null,"errorMessage":"echo: response writer %T does not support flushing (http.Flusher interface)","messagePattern":"echo: response writer %T does not support flushing \\(http\\.Flusher interface\\)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"response.go","lineNumber":85,"sourceCode":"\t\t\tr.Status = http.StatusOK\n\t\t}\n\t\tr.WriteHeader(r.Status)\n\t}\n\tn, err = r.ResponseWriter.Write(b)\n\tr.Size += int64(n)\n\tfor _, fn := range r.afterFuncs {\n\t\tfn()\n\t}\n\treturn\n}\n\n// Flush implements the http.Flusher interface to allow an HTTP handler to flush\n// buffered data to the client.\n// See [http.Flusher](https://golang.org/pkg/net/http/#Flusher)\nfunc (r *Response) Flush() {\n\terr := http.NewResponseController(r.ResponseWriter).Flush()\n\tif err != nil && errors.Is(err, http.ErrNotSupported) {\n\t\tpanic(fmt.Errorf(\"echo: response writer %T does not support flushing (http.Flusher interface)\", r.ResponseWriter))\n\t}\n}\n\n// Hijack implements the http.Hijacker interface to allow an HTTP handler to\n// take over the connection.\n// This method is relevant to Websocket connection upgrades, proxis, and other advanced use cases.\n// See [http.Hijacker](https://golang.org/pkg/net/http/#Hijacker)\nfunc (r *Response) Hijack() (net.Conn, *bufio.ReadWriter, error) {\n\t// newer code should do response hijacking like that\n\t// http.NewResponseController(responseWriter).Hijack()\n\t//\n\t// but there are older libraries that are not aware of `http.NewResponseController` and try to hijack directly\n\t// `hj, ok := resp.(http.Hijacker)` <-- which would fail without Response directly implementing Hijack method\n\t// so for that purpose we need to implement http.Hijacker interface\n\treturn http.NewResponseController(r.ResponseWriter).Hijack()\n}\n\n// Unwrap returns the original http.ResponseWriter.","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/labstack/echo/blob/05489dc1730161df26b72d1ae2a3ba6fb8178fc7/response.go#L67-L103","documentation":"Panicked by Response.Flush() (response.go:85) when http.NewResponseController(r.ResponseWriter).Flush() returns an error that errors.Is http.ErrNotSupported. This means no writer in the wrapped ResponseWriter chain implements http.Flusher, so buffered data cannot be flushed to the client. The %T prints the concrete writer type that lacks Flusher.","triggerScenarios":"Calling c.Response().Flush() (or any code path that flushes, e.g. SSE streaming) when the underlying ResponseWriter does not implement http.Flusher. Common with httptest.ResponseRecorder in tests, or custom writer wrappers that don't forward the Flusher interface.","commonSituations":"Server-Sent Events handlers tested with httptest.ResponseRecorder; middleware that decorates the Response with a writer missing Flusher; running under a server adapter that doesn't expose Flusher.","solutions":["Ensure the ResponseWriter chain implements http.Flusher (the default net/http writer does).","In tests, use a real http.Server/httptest.Server rather than ResponseRecorder for streaming endpoints.","When wrapping echo.Response, embed the underlying writer so Flusher/Hijacker are preserved, or forward Flush explicitly."],"exampleFix":"// before: custom wrapper drops Flusher\ntype myWriter struct{ http.ResponseWriter }\nfunc(w *myWriter) Write(b []byte)(int,error){ return w.ResponseWriter.Write(b) }\n// after: forward Flusher explicitly\nfunc (w *myWriter) Flush() {\n    if f, ok := w.ResponseWriter.(http.Flusher); ok { f.Flush() }\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// Verify the response writer supports flushing before calling Flush (e.g. in SSE handlers).\nfunc canFlush(w http.ResponseWriter) bool {\n    _, ok := w.(http.Flusher)\n    return ok\n}\n\n// usage\nif !canFlush(c.Response().Writer) {\n    return echo.NewHTTPError(http.StatusNotImplemented, \"streaming not supported\")\n}","tryCatchPattern":"// Recover from the Flush panic in streaming handlers if the writer may not flush.\ndefer func() {\n    if r := recover(); r != nil {\n        c.Error(echo.NewHTTPError(http.StatusNotImplemented, \"response writer does not support flushing\"))\n    }\n}()\nc.Response().Flush()","preventionTips":["Do not replace echo.Response with a writer that drops http.Flusher.","Use httptest.NewServer for streaming/SSE tests instead of ResponseRecorder.","When wrapping the writer, forward Flush() to the underlying Flusher."],"tags":["response","flusher","streaming","sse","runtime","panic"],"analyzedSha":"05489dc1730161df26b72d1ae2a3ba6fb8178fc7","analyzedAt":"2026-08-04T21:32:47.783Z","schemaVersion":2}