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
After confirming the id is valid JSON, PluginRPCID.UnmarshalJSON enforces the JSON-RPC id rules: it must be a string (starts with '"'), a number (starts with '-' or 0-9), or the literal null. Any other JSON value — typically an object or array — is rejected with "invalid id field: must be string, number, null or omitted".
Solutions
- Change the id to a plain string or number (or null) as required by the JSON-RPC id specification.
- Move any extra correlation metadata into params instead of the id field.
- Fix the client's id type declaration so it serializes as a scalar.
Example fix
// before
{"id": {"requestId": 42}}
// after
{"id": 42} Defensive patterns
Strategy: validation
Validate before calling
function checkRpcIdShape(id) {
if (!(typeof id === "string" || (typeof id === "number" && Number.isFinite(id)) || id === null)) {
throw new Error("id must be a JSON-RPC scalar: string, number, or null");
}
} Type guard
const isScalarRpcId = (id) => id === null || typeof id === "string" || (typeof id === "number" && !Number.isNaN(id));
Try / catch
try { await rpcCall(method, params, id); } catch (e) { if (String(e).includes("invalid id field")) { throw new Error("wrap id metadata into params; id must stay a scalar"); } throw e; } Prevention
- Type the RPC id as string | number | null in the client.
- Never send objects or arrays as the JSON-RPC id.
- Put correlation metadata in params, not the id.
When it happens
Trigger: Unmarshalling a plugin RPC message whose id is a JSON object or array (data[0] is '{' or '['), e.g. {"id": {"n": 1}} or {"id": ["a"]}.
Common situations: A client library that types id as a generic object serializes a structured id; correlation IDs wrapped in objects for extra metadata; mismatched RPC dialects between plugin and kernel.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- builtin color must not be null
- builtin style must not be null
- Conf.Language(317)
- createDocTree definition must be a list
- createDocTree document list must not be empty
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/b564db91b827edaf.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/apicontract/plugin_rpc.go:20
import (
"bytes"
"encoding/json"
"fmt"
"io"
"strings"
)
type PluginRPCID struct{ value JSONValue }
func (id PluginRPCID) MarshalJSON() ([]byte, error) { return json.Marshal(id.value) }
func (id *PluginRPCID) UnmarshalJSON(data []byte) error {
data = bytes.TrimSpace(data)
if !json.Valid(data) || len(data) == 0 {
return fmt.Errorf("invalid RPC ID")
}
if data[0] != '"' && data[0] != '-' && (data[0] < '0' || data[0] > '9') && string(data) != "null" {
return fmt.Errorf("invalid id field: must be string, number, null or omitted")
}
return json.Unmarshal(data, &id.value)
}
type PluginRPCParams struct{ value JSONValue }
type PluginRPCRequestFields struct {
JSONRPC string `json:"jsonrpc" api:"const=\"2.0\""`
Method string `json:"method"`
Params *PluginRPCParams `json:"params" api:"optional"`
ID *PluginRPCID `json:"id" api:"optional"`
}
type PluginRPCSuccess struct {
JSONRPC string `json:"jsonrpc" api:"const=\"2.0\""`
Result JSONValue `json:"result"`
ID PluginRPCID `json:"id"`
}View on GitHub (pinned to 9f775e8a12)