{"id":"95bef54f59b14171","repo":"labstack/echo","slug":"responsewriter-does-not-implement-unwrap-http-r","errorCode":null,"errorMessage":"ResponseWriter does not implement 'Unwrap() http.ResponseWriter' interface or unwrap to *echo.Response","messagePattern":"ResponseWriter does not implement 'Unwrap\\(\\) http\\.ResponseWriter' interface or unwrap to \\*echo\\.Response","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"response.go","lineNumber":130,"sourceCode":"\tr.afterFuncs = nil\n\tr.ResponseWriter = w\n\tr.Size = 0\n\tr.Status = http.StatusOK\n\tr.Committed = false\n}\n\n// UnwrapResponse unwraps given ResponseWriter to return contexts original Echo Response. rw has to implement\n// following method `Unwrap() http.ResponseWriter`\nfunc UnwrapResponse(rw http.ResponseWriter) (*Response, error) {\n\tfor {\n\t\tswitch t := rw.(type) {\n\t\tcase *Response:\n\t\t\treturn t, nil\n\t\tcase interface{ Unwrap() http.ResponseWriter }:\n\t\t\trw = t.Unwrap()\n\t\t\tcontinue\n\t\tdefault:\n\t\t\treturn nil, errors.New(\"ResponseWriter does not implement 'Unwrap() http.ResponseWriter' interface or unwrap to *echo.Response\")\n\t\t}\n\t}\n}\n\n// delayedStatusWriter is a wrapper around http.ResponseWriter that delays writing the status code until first Write is called.\n// This allows (global) error handler to decide correct status code to be sent to the client.\ntype delayedStatusWriter struct {\n\thttp.ResponseWriter\n\tcommitted bool\n\tstatus    int\n}\n\nfunc (w *delayedStatusWriter) WriteHeader(statusCode int) {\n\t// in case something else writes status code explicitly before us we need mark response committed\n\tw.committed = true\n\tw.ResponseWriter.WriteHeader(statusCode)\n}\n","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/labstack/echo/blob/05489dc1730161df26b72d1ae2a3ba6fb8178fc7/response.go#L112-L148","documentation":"Returned by echo.UnwrapResponse when the given http.ResponseWriter cannot be unwrapped down to a *echo.Response. UnwrapResponse walks the Unwrap() chain (each wrapper must implement Unwrap() http.ResponseWriter) looking for a *Response; if it hits a writer that has neither type it gives up. This helper is used internally (e.g., by the HEAD-request writer and error-handling path) but can be called by user middleware too.","triggerScenarios":"Passing an http.ResponseWriter obtained outside Echo's request lifecycle, or a custom wrapper that does not implement Unwrap() (or whose Unwrap chain never reaches *echo.Response) to echo.UnwrapResponse.","commonSituations":"User middleware replaces c.Response() with a custom writer that does not implement Unwrap(); testing with httptest.NewRecorder() directly against code that calls UnwrapResponse; or a third-party wrapper that fails to forward Unwrap.","solutions":["Make any custom http.ResponseWriter wrapper implement Unwrap() http.ResponseWriter returning the underlying writer, so the chain reaches *echo.Response.","If you only need the *echo.Response, access it via c.Response() from the Context rather than unwrapping an arbitrary writer.","Check the returned error from UnwrapResponse before using the *Response (it is a (resp, err) signature).","When testing, wrap httptest.NewRecorder() in an echo.Response via echo.NewResponse(rec, logger) instead of passing the bare recorder."],"exampleFix":"// before: custom wrapper breaks the unwrap chain\ntype myWriter struct{ http.ResponseWriter }\n// after: implement Unwrap so ResponseController / UnwrapResponse work\ntype myWriter struct{ http.ResponseWriter }\nfunc (w *myWriter) Unwrap() http.ResponseWriter { return w.ResponseWriter }","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func isUnwrappable(rw http.ResponseWriter) bool {\n    _, err := echo.UnwrapResponse(rw)\n    return err == nil\n}\n\n// or check the interface directly:\nfunc hasUnwrap(rw http.ResponseWriter) bool {\n    _, ok := rw.(interface{ Unwrap() http.ResponseWriter })\n    if !ok {\n        _, ok = rw.(*echo.Response)\n    }\n    return ok\n}","tryCatchPattern":null,"preventionTips":["Implement Unwrap() http.ResponseWriter on any custom ResponseWriter wrapper so the chain reaches *echo.Response.","Prefer c.Response() over manually unwrapping writers when you just need the Echo response.","In tests, wrap httptest.NewRecorder() with echo.NewResponse(rec, logger) rather than passing the bare recorder.","Always check the error returned by echo.UnwrapResponse before using the result."],"tags":["echo","response","http","type-assertion","runtime"],"analyzedSha":"05489dc1730161df26b72d1ae2a3ba6fb8178fc7","analyzedAt":"2026-08-04T21:32:47.783Z","schemaVersion":2}