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

JSON-RPC 2.0 restricts the 'id' member to string, number, or null (or the field may be omitted for notifications). JsonRpcRequest.UnmarshalJSON enforces this: if id exists, is not null, and is neither string nor float64, it fails with 'invalid id field: must be string, number, null or omitted'. This keeps correlation IDs spec-compliant so responses can be matched to requests.

Solutions

  1. Use a string or number for id, or omit it entirely for notifications
  2. Replace boolean/object id values with a generated numeric or string identifier
  3. Validate the payload schema before sending (id must be scalar or null)
  4. Check client library settings for automatic ID generation and force scalar IDs

Example fix

// before
{"jsonrpc": "2.0", "method": "ping", "id": true}
// after
{"jsonrpc": "2.0", "method": "ping", "id": "req-1"}
Defensive patterns

Strategy: validation

Validate before calling

function validId(id) { return id === undefined || id === null || typeof id === "string" || typeof id === "number"; }

Type guard

const isRpcId = (v) => v === undefined || v === null || typeof v === "string" || (typeof v === "number" && Number.isFinite(v));

Try / catch

try { return await rpcSend(payload); } catch (e) { if (String(e).includes("invalid id field")) { payload.id = String(payload.id); return rpcSend(payload); } throw e; }

Prevention

When it happens

Trigger: Sending "id": true/false (boolean), "id": {"n":1} (object), or "id": [1] (array); clients auto-generating UUID objects instead of strings; batching frameworks that inject non-scalar IDs.

Common situations: Custom clients using boolean flags as IDs; JavaScript engines passing objects; test scripts with id: true to mean 'request'; serializers that box numbers into objects.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at kernel/plugin/rpc.go:130

	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 9f775e8a12)