siyuan-note/siyuan · error

invalid jsonrpc version: %s

Error message

invalid jsonrpc version: %s

What it means

Returned when the jsonrpc field exists but its value is not exactly "2.0" (JsonRpcVersion). The version string is interpolated into the message so the offending value is visible. Any other version (1.0, 2, "2") is rejected.

Source

Thrown at kernel/plugin/rpc.go:114

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

	r.JsonRpc = request.JsonRpc.Value
	r.Method = request.Method.Value

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Use exactly the string "2.0" for jsonrpc.
  2. Centralize envelope construction so the version is not hand-typed per call.
  3. Log the raw body on this error to see what value was sent.

Example fix

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

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

Strategy: validation

Validate before calling

if (req.jsonrpc !== '2.0') throw new Error('jsonrpc must be exactly "2.0"');

Type guard

function isJsonRpc2(o: unknown): boolean { return !!o && typeof o === 'object' && (o as any).jsonrpc === '2.0'; }

Prevention

When it happens

Trigger: Client sends {"jsonrpc":"2.0"...} with a typo, or "jsonrpc":"1.0"/"2", or a numeric 2 instead of the string "2.0".

Common situations: Wrong spec version from a legacy client, a string/number coercion bug, or copy-paste from JSON-RPC 1.0 docs.

Understand the failure class

Related errors


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