siyuan-note/siyuan · error

right document version is required

Error message

right document version is required

What it means

Symmetric to the left-side check, the diffDocVersions decoder requires a `right` field holding a document version reference object. Unmarshal failure or a nil result (absent, null, or non-object value) produces 'right document version is required'.

Solutions

  1. Send "right" as a version reference object alongside left
  2. Resolve the second history version before invoking the diff endpoint
  3. Verify the payload with both keys: {"left": {...}, "right": {...}}

Example fix

// before
{"left": {"type": "id", "id": "20240101110000-abcdef0"}}
// after
{"left": {"type": "id", "id": "20240101110000-abcdef0"}, "right": {"type": "id", "id": "20240101120000-abcdef1"}}
Defensive patterns

Strategy: validation

Validate before calling

if (!isValidVersionRef(body.right)) throw new Error("right version ref required");

Type guard

const isVersionRef = (v) => v !== null && typeof v === "object" && typeof v.type === "string";

Prevention

When it happens

Trigger: POSTing to /api/history/diffDocVersions with only `left` set, "right": null, or right as a non-object value.

Common situations: Selecting 'compare with previous' where the right version failed to resolve and the client sent null; partial request construction.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at kernel/apicontract/history_diff.go:55

	Differences   []*DocVersionDifference `json:"differences"`
	Large         bool                    `json:"large"`
	Fallback      bool                    `json:"fallback"`
	Message       string                  `json:"message"`
	TitleModified bool                    `json:"titleModified"`
}

func init() {
	DiffDocVersions.decodeRequest = func(reader io.Reader) (request DiffDocVersionsRequest, err error) {
		fields, err := blockRequestFields(reader, "/api/history/diffDocVersions")
		if err != nil {
			return request, err
		}
		var left, right map[string]json.RawMessage
		if json.Unmarshal(fields["left"], &left) != nil || left == nil {
			return request, fmt.Errorf("left document version is required")
		}
		if json.Unmarshal(fields["right"], &right) != nil || right == nil {
			return request, fmt.Errorf("right document version is required")
		}
		if request.Left, err = decodeDocVersionRef(left); err != nil {
			return request, err
		}
		request.Right, err = decodeDocVersionRef(right)
		return request, err
	}
}

func decodeDocVersionRef(fields map[string]json.RawMessage) (request DocVersionRef, err error) {
	if request.Type, err = legacyField[string](fields, "type", "String", true); err != nil {
		return request, err
	}
	request.Type = strings.TrimSpace(request.Type)
	if request.Type == "" {
		return request, fmt.Errorf("Field [type] must not be empty")
	}
	if request.ID, err = legacyField[string](fields, "id", "String", false); err != nil {

View on GitHub (pinned to 9f775e8a12)