gofr-dev/gofr · error
response writer does not support hijacking
Error message
response writer does not support hijacking
What it means
errHijackNotSupported is a sentinel in GoFr's logging middleware returned by StatusResponseWriter.Hijack when the wrapped http.ResponseWriter does not implement http.Hijacker. Connection hijacking (needed for WebSockets and upgraded protocols) is only possible if the underlying writer supports it, so this error surfaces that limitation. It's normally wrapped by the 'cannot hijack connection' error.
Source
Thrown at pkg/gofr/http/middleware/logger.go:19
package middleware
import (
"bufio"
"encoding/json"
"errors"
"fmt"
"io"
"net"
"net/http"
"runtime/debug"
"strings"
"sync"
"time"
"go.opentelemetry.io/otel/trace"
)
var errHijackNotSupported = errors.New("response writer does not support hijacking")
// JSON envelope keys for the panic-recovery error response written by
// panicRecovery. Defined as constants so the same spellings stay
// consistent across the package and the goconst linter is satisfied.
const (
envelopeCodeKey = "code"
envelopeStatusKey = "status"
envelopeMessageKey = "message"
)
// StatusResponseWriter Defines own Response Writer to be used for logging of status - as http.ResponseWriter does not let us read status.
type StatusResponseWriter struct {
http.ResponseWriter
status int
// wroteHeader keeps a flag to keep a check that the framework do not attempt to write the header again. This was previously causing
// `superfluous response.WriteHeader call`. This is particularly helpful in scenarios where the developer has already written header
// in any custom middlewares.
wroteHeader boolView on GitHub (pinned to 187eb24962)
Solutions
- Ensure the underlying ResponseWriter implements http.Hijacker (forward Hijack in custom wrappers)
- Register WebSocket endpoints so they aren't wrapped by non-hijackable middleware writers
- In tests use a real httptest server or a hijacker-capable fake instead of ResponseRecorder
- Check for errors.Is(err, middleware.ErrHijackNotSupported) and fall back to a plain connection path
Example fix
// before
type gzipResponseWriter struct{ http.ResponseWriter } // no Hijack -> errHijackNotSupported
// after
type gzipResponseWriter struct{ http.ResponseWriter }
func (w *gzipResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
if h, ok := w.ResponseWriter.(http.Hijacker); ok { return h.Hijack() }
return nil, nil, http.ErrNotSupported
} Defensive patterns
Strategy: type-guard
Validate before calling
if _, ok := underlying.(http.Hijacker); !ok {
return errors.New("underlying response writer does not support hijacking; websocket upgrade will fail")
} Type guard
func supportsHijack(w http.ResponseWriter) bool {
_, ok := w.(http.Hijacker)
return ok
} Try / catch
conn, rw, err := srw.Hijack()
if err != nil {
if errors.Is(err, middleware.ErrHijackNotSupported) {
// degrade: respond normally instead of upgrading
http.Error(srw, "upgrade unsupported", http.StatusInternalServerError)
return
}
return err
} Prevention
- Implement Hijack in every custom ResponseWriter wrapper by delegating to the inner writer
- Keep WebSocket routes outside non-hijackable middleware chains
- Use httptest.NewServer (not ResponseRecorder) for upgrade tests
- Audit middleware order whenever adding logging/compression layers
When it happens
Trigger: Calling Hijack() on a StatusResponseWriter whose underlying ResponseWriter lacks a Hijack() method, e.g. when a WebSocket upgrade handler runs through a writer chain (logging, gzip, test fakes) that doesn't implement http.Hijacker.
Common situations: Adding logging or compression middleware above a WebSocket endpoint, using httptest.ResponseRecorder in tests, or custom reverse-proxy writers that don't forward the Hijacker interface.
Related errors
- %w: cannot hijack connection
- Could not open WebSocket connection
- errFileNotOpenForReading
- response retrieved is nil
- s3 backend did not honor the requested byte range
AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01).
Data as JSON: /api/errors/5d53d326f05e5964.
Report an issue: GitHub.