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
- Trim the control-frame payload to 125 bytes or fewer
- Move large data out of control frames into data frames (types 1/2)
- Reject or split oversized close reasons on the producing side before sending
- 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
- Cap close/ping/pong payloads at 125 bytes at the send site
- Keep large diagnostics out of control frames; use data frames
- Add a shared constant MAX_CONTROL_PAYLOAD = 125
- Fuzz-test frame validation with oversized control payloads
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
- plugin WebSocket control frame exceeds 125 bytes
- encrypted asset metadata is too large
- endpoint does not declare raw WebSocket frames
- failed to convert request value to object
- invalid card cover image
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)