siyuan-note/siyuan · error

WebSocket control frame exceeds 125 bytes

Error message

WebSocket control frame exceeds 125 bytes

What it means

Within a raw WebSocket endpoint, a frame whose type matches an allowed type (from Raw.Frames) is additionally checked against the RFC 6455 rule that control frames (types >= 8, i.e. close 8, ping 9, pong 10) carry at most 125 bytes of payload. An allowed control frame larger than 125 bytes is rejected with this error.

Solutions

  1. Trim the control-frame payload to 125 bytes or fewer
  2. Move large data out of control frames into data frames (types 1/2)
  3. Reject or split oversized close reasons on the producing side before sending
  4. Add a payload-length check at the call site before invoking validation

Example fix

// before
payload := append(closeReasonBytes, extraDiagnostics...) // > 125 bytes
ValidateRawWebSocketFrame("GET", "/ws", true, 8, payload)
// after
if len(payload) > 125 { payload = payload[:125] }
ValidateRawWebSocketFrame("GET", "/ws", true, 8, payload)
Defensive patterns

Strategy: validation

Validate before calling

if (frameType >= 8 && payload.length > 125) throw new Error("control frame exceeds 125 bytes (RFC 6455)");

Type guard

function isLegalControlPayload(t, p) { return t < 8 || p.length <= 125; }

Try / catch

try { bundle.ValidateRawWebSocketFrame(method, path, true, frameType, payload); } catch (e) { if (String(e).includes("exceeds 125 bytes")) { payload = payload.slice(0, 125); retry; } else throw e; }

Prevention

When it happens

Trigger: ValidateRawWebSocketFrame is called with frameType 8/9/10 (close/ping/pong) and len(payload) > 125 on an endpoint whose Raw.Frames includes that control type.

Common situations: Applications stuffing arbitrary status data into close/ping/pong payloads; ping keepalive implementations attaching large heartbeat blobs; fuzz or malformed-client tests sending oversized control frames.

Understand the failure class

Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/6e4161b0694158b1. Report an issue: GitHub.

Appendix: source

Thrown at kernel/apicontract/broadcast_protocol.go:88

			if endpoint.SSE == nil || endpoint.SSE.Raw == nil {
				return fmt.Errorf("endpoint does not declare raw SSE events")
			}
			return nil
		}
	}
	return fmt.Errorf("unregistered API contract: %s %s", method, path)
}

func (b *Bundle) ValidateRawWebSocketFrame(method, path string, incoming bool, frameType int, payload []byte) error {
	for _, endpoint := range b.Endpoints {
		if endpoint.Method == method && endpoint.Path == path {
			if endpoint.WebSocket == nil || endpoint.WebSocket.Raw == nil {
				return fmt.Errorf("endpoint does not declare raw WebSocket frames")
			}
			for _, allowed := range endpoint.WebSocket.Raw.Frames {
				if frameType == allowed {
					if frameType >= 8 && len(payload) > 125 {
						return fmt.Errorf("WebSocket control frame exceeds 125 bytes")
					}
					return nil
				}
			}
			return fmt.Errorf("undeclared raw WebSocket frame: %d", frameType)
		}
	}
	return fmt.Errorf("unregistered API contract: %s %s", method, path)
}

View on GitHub (pinned to 9f775e8a12)