siyuan-note/siyuan · error

invalid id field: must be string, number, null or omitted

Error message

invalid id field: must be string, number, null or omitted

What it means

Returned when the id field is present but is neither a string, a number (float64 after JSON decode), nor null. The kernel allows id to be omitted (notification), null, a string, or a number; booleans, objects, and arrays are rejected per the JSON-RPC 2.0 spec.

Source

Thrown at kernel/plugin/rpc.go:128

	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")
	}

	r.JsonRpc = request.JsonRpc.Value
	r.Method = request.Method.Value
	r.Params = request.Params
	r.ID = request.ID
	return nil
}

// IsNotification returns true if this request is a notification (no ID field).
func (r *JsonRpcRequest) IsNotification() bool {
	return r.ID.Exists == false
}

// Validate validates the JSON-RPC request structure.
func (r *JsonRpcRequest) Validate() *JsonRpcError {
	// params is optional, but if present must be either an array (for positional parameters) or an object (for named parameters)
	if !r.Params.Exists {

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Use a string or integer id, or null/omit it for notifications.
  2. Generate ids from a counter: let id = 0; ... id: ++id.
  3. Validate typeof id === 'string' || typeof id === 'number' before sending.

Example fix

// before
{ jsonrpc: '2.0', id: { batch: 1 }, method: 'm' }

// after
{ jsonrpc: '2.0', id: 'batch-1', method: 'm' }
Defensive patterns

Strategy: type-guard

Validate before calling

function isValidId(id: unknown): boolean { return id === undefined || id === null || typeof id === 'string' || typeof id === 'number'; }

Type guard

function isJsonRpcId(id: unknown): id is string | number | null | undefined { return id === undefined || id === null || typeof id === 'string' || typeof id === 'number'; }

Prevention

When it happens

Trigger: Client sends {"jsonrpc":"2.0","method":"m","id":true} or id as an object/array.

Common situations: Reusing a JS boolean or object as an id, or a serialization quirk that wraps id in an extra layer.

Related errors


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