gorilla/websocket · error
websocket: invalid control frame
Error message
websocket: invalid control frame
What it means
This sentinel error (errInvalidControlFrame) is returned when the library reads a control frame (ping, pong, or close) that violates the WebSocket protocol (RFC 6455). Control frames must not be fragmented, must have a payload of 125 bytes or less, and must have a valid opcode. The library rejects them rather than silently tolerating protocol violations.
Source
Thrown at conn.go:180
// *CloseError with a code not in the list of expected codes.
func IsUnexpectedCloseError(err error, expectedCodes ...int) bool {
if e, ok := err.(*CloseError); ok {
for _, code := range expectedCodes {
if e.Code == code {
return false
}
}
return true
}
return false
}
var (
errWriteTimeout = &netError{msg: "websocket: write timeout", timeout: true, temporary: true}
errUnexpectedEOF = &CloseError{Code: CloseAbnormalClosure, Text: io.ErrUnexpectedEOF.Error()}
errBadWriteOpCode = errors.New("websocket: bad write message type")
errWriteClosed = errors.New("websocket: write closed")
errInvalidControlFrame = errors.New("websocket: invalid control frame")
)
// maskRand is an io.Reader for generating mask bytes. The reader is initialized
// to crypto/rand Reader. Tests swap the reader to a math/rand reader for
// reproducible results.
var maskRand = rand.Reader
// newMaskKey returns a new 32 bit value for masking client frames.
func newMaskKey() [4]byte {
var k [4]byte
_, _ = io.ReadFull(maskRand, k[:])
return k
}
func isControl(frameType int) bool {
return frameType == CloseMessage || frameType == PingMessage || frameType == PongMessage
}
View on GitHub (pinned to e064f32e36)
Solutions
- Inspect the peer implementation and fix it to send unfragmented control frames with payloads <= 125 bytes (RFC 6455 section 5.5)
- Check for proxies/load balancers in the path that rewrite WebSocket frames and configure them to pass frames through untouched
- Update the peer library to a version that complies with RFC 6455 control-frame rules
- If the peer is trusted, capture the traffic and verify the frame header bits (FIN=1, valid opcode 0x8-0xA, length<=125)
Defensive patterns
Strategy: validation
Prevention
- Use RFC 6455-compliant peer libraries on both ends
- Test interop against well-known clients/servers before deploying proxies
- Avoid custom intermediaries that rewrite WebSocket frames
When it happens
Trigger: Reading from a Conn whose peer sent a fragmented ping/pong/close frame, a control frame with a payload larger than 125 bytes, or an invalid reserved opcode on a control frame; detected inside advanceFrame while processing an incoming control frame.
Common situations: Talking to a non-conformant WebSocket server or client, an intermediary proxy that mangles frames, or custom peer implementations that get control-frame framing wrong; also seen when the TCP stream is being corrupted by a misbehaving intermediate.
Related errors
- websocket: bad handshake
- websocket: invalid compression negotiation
- malformed ws or wss URL
- websocket: duplicate header not allowed:
- websocket: protocol %q was given but is not supported;sharin
AI-assisted analysis of gorilla/websocket@e064f32e36 (2026-08-31).
Data as JSON: /api/errors/4e21363b8161da53.
Report an issue: GitHub.