{"record":{"id":"a6792527d53d4dc4","repo":"siyuan-note/siyuan","slug":"undeclared-raw-websocket-frame-d","errorCode":null,"errorMessage":"undeclared raw WebSocket frame: %d","messagePattern":"undeclared raw WebSocket frame: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/apicontract/broadcast_protocol.go","lineNumber":93,"sourceCode":"\t}\n\treturn fmt.Errorf(\"unregistered API contract: %s %s\", method, path)\n}\n\nfunc (b *Bundle) ValidateRawWebSocketFrame(method, path string, incoming bool, frameType int, payload []byte) error {\n\tfor _, endpoint := range b.Endpoints {\n\t\tif endpoint.Method == method && endpoint.Path == path {\n\t\t\tif endpoint.WebSocket == nil || endpoint.WebSocket.Raw == nil {\n\t\t\t\treturn fmt.Errorf(\"endpoint does not declare raw WebSocket frames\")\n\t\t\t}\n\t\t\tfor _, allowed := range endpoint.WebSocket.Raw.Frames {\n\t\t\t\tif frameType == allowed {\n\t\t\t\t\tif frameType >= 8 && len(payload) > 125 {\n\t\t\t\t\t\treturn fmt.Errorf(\"WebSocket control frame exceeds 125 bytes\")\n\t\t\t\t\t}\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn fmt.Errorf(\"undeclared raw WebSocket frame: %d\", frameType)\n\t\t}\n\t}\n\treturn fmt.Errorf(\"unregistered API contract: %s %s\", method, path)\n}\n","sourceCodeStart":75,"sourceCodeEnd":98,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/apicontract/broadcast_protocol.go#L75-L98","documentation":"ValidateRawWebSocketFrame checks that an incoming/outgoing WebSocket frame type is declared in the endpoint's raw WebSocket contract (RawWebSocketDefinition.Frames, defaulting to [1,2,8,9,10]). This error means the frame opcode used is not among the opcodes the endpoint declared, so the kernel rejects the frame as protocol-incompatible with its registered contract.","triggerScenarios":"Calling Bundle.ValidateRawWebSocketFrame with a frameType (WebSocket opcode) that is not listed in the endpoint's Raw.Frames slice — e.g. opcode 0 (continuation), 3-7 (reserved data frames), or 11-15 (reserved control frames) against an endpoint declared via RawWebSocketOptions().","commonSituations":"Client code sends a continuation frame (opcode 0) as a standalone frame; a proxy or library re-frames messages with an opcode outside 1/2/8/9/10; a new opcode is used after the contract's Frames list was authored; pinging with a nonstandard frame type.","solutions":["Check the frame's WebSocket opcode and use only declared ones: text (1), binary (2), close (8), ping (9), pong (10)","If a new opcode is genuinely needed, update the endpoint's RawWebSocketDefinition.Frames to declare it and keep the contract schema in sync","Log frameType at the call site to confirm which opcode is actually being sent before changing code"],"exampleFix":"// before\nconn.WriteMessage(0, payload) // continuation opcode not declared\n// after\nconn.WriteMessage(1, payload) // declared text frame","handlingStrategy":"validation","validationCode":"const allowedFrames = [1, 2, 8, 9, 10];\nif (!allowedFrames.includes(frameType)) throw new Error(`frame type ${frameType} not declared`);","typeGuard":"const isDeclaredFrame = (t) => [1, 2, 8, 9, 10].includes(t);","tryCatchPattern":null,"preventionTips":["Only send text (1), binary (2), close (8), ping (9), pong (10) frames","Never emit continuation or reserved opcodes (0, 3-7, 11-15)","Keep control frames (>=8) at 125 bytes or less to also avoid the size error"],"tags":["websocket","protocol-validation","api-contract"],"backgroundTag":"unsupported-operation","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}