siyuan-note/siyuan · error

missing jsonrpc field

Error message

missing jsonrpc field

What it means

Returned by JsonRpcRequest.UnmarshalJSON when the decoded JSON object has no 'jsonrpc' field. The kernel uses util.Optional to distinguish absent vs null, and an absent jsonrpc field means the message is not a valid JSON-RPC 2.0 request. This fires before version comparison.

Source

Thrown at kernel/plugin/rpc.go:111

}

func (r *JsonRpcRequest) UnmarshalJSON(data []byte) error {
	decoder := json.NewDecoder(bytes.NewReader(data))
	// decoder.DisallowUnknownFields() // Reject unknown fields violates the JSON-RPC spec
	type JsonRpcRequestObject struct {
		JsonRpc util.Optional[string] `json:"jsonrpc"`
		Method  util.Optional[string] `json:"method"`
		Params  util.Optional[any]    `json:"params"`
		ID      util.Optional[any]    `json:"id"`
	}
	request := JsonRpcRequestObject{}
	if err := decoder.Decode(&request); err != nil {
		return err
	}

	// Validate jsonrpc field
	if !request.JsonRpc.Exists {
		return fmt.Errorf("missing jsonrpc field")
	}
	if request.JsonRpc.Value != JsonRpcVersion {
		return fmt.Errorf("invalid jsonrpc version: %s", request.JsonRpc.Value)
	}

	// Validate method field
	if !request.Method.HasValue() {
		return fmt.Errorf("missing method field")
	}

	// Validate id field
	if !request.ID.Exists {
	} else if request.ID.IsNull {
	} else if _, ok := request.ID.Value.(string); ok {
	} else if _, ok := request.ID.Value.(float64); ok {
	} else {
		return fmt.Errorf("invalid id field: must be string, number, null or omitted")
	}

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Include "jsonrpc":"2.0" in every request body.
  2. Build requests with a shared helper that always adds jsonrpc, method, and id.
  3. Validate the envelope with JSON.parse + field check before sending.

Example fix

// before
fetch(url, { method: 'POST', body: JSON.stringify({ method: 'doStuff', params: [] }) });

// after
fetch(url, { method: 'POST', body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'doStuff', params: [] }) });
Defensive patterns

Strategy: validation

Validate before calling

function hasJsonRpc(o: any): boolean { return !!o && typeof o === 'object' && 'jsonrpc' in o; }

Type guard

function isJsonRpcEnvelope(o: unknown): o is { jsonrpc: '2.0'; method: string; params?: unknown; id?: string | number | null } { return !!o && typeof o === 'object' && (o as any).jsonrpc === '2.0' && typeof (o as any).method === 'string'; }

Prevention

When it happens

Trigger: A plugin's RPC handler receives a JSON body like {"method":"foo","params":[]} with no jsonrpc field, or a malformed/empty object.

Common situations: Client sends a raw method call without the JSON-RPC envelope, or a proxy strips unknown fields, or a hand-built fetch payload forgot the jsonrpc:'2.0'.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/ab679e8f81dad770. Report an issue: GitHub.