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

  1. Inspect the peer implementation and fix it to send unfragmented control frames with payloads <= 125 bytes (RFC 6455 section 5.5)
  2. Check for proxies/load balancers in the path that rewrite WebSocket frames and configure them to pass frames through untouched
  3. Update the peer library to a version that complies with RFC 6455 control-frame rules
  4. 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

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


AI-assisted analysis of gorilla/websocket@e064f32e36 (2026-08-31). Data as JSON: /api/errors/4e21363b8161da53. Report an issue: GitHub.