siyuan-note/siyuan · error

endpoint does not declare raw WebSocket frames

Error message

endpoint does not declare raw WebSocket frames

What it means

ValidateRawWebSocketFrame finds the endpoint by method+path and requires its WebSocket definition to have Raw mode enabled. If the endpoint is a typed (non-raw) WebSocket or has no WebSocket definition, this error is returned before frame-type checking. It guards against validating raw frames against endpoints with typed message schemas.

Solutions

  1. Declare the endpoint with RawWebSocketOptions().WebSocket in the contract
  2. Confirm the method and path match the raw WebSocket endpoint exactly
  3. Use the typed WebSocket validation path if the endpoint declares Incoming/Outgoing schemas
  4. Rebuild the bundle after contract changes

Example fix

// before
// endpoint declared with Incoming/Outgoing schemas only
bundle.ValidateRawWebSocketFrame("GET", "/ws", true, 1, payload)
// after
WebSocket: RawWebSocketOptions().WebSocket
bundle.ValidateRawWebSocketFrame("GET", "/ws", true, 1, payload)
Defensive patterns

Strategy: validation

Validate before calling

const ep = bundle.Endpoints.find(e => e.Method === method && e.Path === path);
if (!ep) throw new Error("unregistered: " + method + " " + path);
if (!ep.WebSocket?.Raw) throw new Error("endpoint is not raw WebSocket");

Type guard

function isRawWSEndpoint(ep) { return !!ep?.WebSocket?.Raw; }

Try / catch

try { bundle.ValidateRawWebSocketFrame(method, path, incoming, frameType, payload); } catch (e) { if (String(e).includes("does not declare raw WebSocket frames")) useTypedFrameValidation(); else throw e; }

Prevention

When it happens

Trigger: Calling bundle.ValidateRawWebSocketFrame for an endpoint whose contract sets Incoming/Outgoing schemas but no Raw definition, or that has no WebSocket contract at all.

Common situations: Server migrated a WebSocket endpoint to typed messages while the raw-frame validator client remained; wrong method/path matching a non-WebSocket endpoint; contract definitions out of sync with runtime.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at kernel/apicontract/broadcast_protocol.go:83

// ValidateRawSSEEvent 校验事件协议;事件数据是原始字节,不进行 JSON 解码或 Base64 转码。
func (b *Bundle) ValidateRawSSEEvent(method, path, name, id string, retry uint, payload []byte) error {
	for _, endpoint := range b.Endpoints {
		if endpoint.Method == method && endpoint.Path == path {
			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)