{"record":{"id":"4e21363b8161da53","repo":"gorilla/websocket","slug":"websocket-invalid-control-frame","errorCode":null,"errorMessage":"websocket: invalid control frame","messagePattern":"websocket: invalid control frame","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"conn.go","lineNumber":180,"sourceCode":"// *CloseError with a code not in the list of expected codes.\nfunc IsUnexpectedCloseError(err error, expectedCodes ...int) bool {\n\tif e, ok := err.(*CloseError); ok {\n\t\tfor _, code := range expectedCodes {\n\t\t\tif e.Code == code {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\t}\n\treturn false\n}\n\nvar (\n\terrWriteTimeout        = &netError{msg: \"websocket: write timeout\", timeout: true, temporary: true}\n\terrUnexpectedEOF       = &CloseError{Code: CloseAbnormalClosure, Text: io.ErrUnexpectedEOF.Error()}\n\terrBadWriteOpCode      = errors.New(\"websocket: bad write message type\")\n\terrWriteClosed         = errors.New(\"websocket: write closed\")\n\terrInvalidControlFrame = errors.New(\"websocket: invalid control frame\")\n)\n\n// maskRand is an io.Reader for generating mask bytes. The reader is initialized\n// to crypto/rand Reader. Tests swap the reader to a math/rand reader for\n// reproducible results.\nvar maskRand = rand.Reader\n\n// newMaskKey returns a new 32 bit value for masking client frames.\nfunc newMaskKey() [4]byte {\n\tvar k [4]byte\n\t_, _ = io.ReadFull(maskRand, k[:])\n\treturn k\n}\n\nfunc isControl(frameType int) bool {\n\treturn frameType == CloseMessage || frameType == PingMessage || frameType == PongMessage\n}\n","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/gorilla/websocket/blob/e064f32e3674d9d79a8fd417b5bc06fa5c6cad8f/conn.go#L162-L198","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["websocket","protocol-violation","rfc6455"],"backgroundTag":"websocket-protocol-violation","analyzedSha":"e064f32e3674d9d79a8fd417b5bc06fa5c6cad8f","analyzedAt":"2026-08-31T12:40:58.222Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}