siyuan-note/siyuan · error

Field [ ] has an invalid constant

Error message

Field [%s] has an invalid constant

What it means

This error comes from the SiYuan kernel's strict request decoder in kernel/apicontract/decode.go (decodeRequestFields). When a contract field is declared with a fixed constant (a pinned value), the decoder unmarshals the submitted value and compares it with the declared constant using reflect.DeepEqual; any difference means the client sent a value that violates the API contract. It protects endpoints whose fields must equal a specific constant and cannot be freely chosen by the caller.

Solutions

  1. Read the endpoint's contract definition in kernel/apicontract/ and set the field exactly to the declared constant value
  2. Remove the field from your payload if the contract marks it as a constant that the server injects itself
  3. Update your client/plugin code to match the current SiYuan API version's contract
  4. If you believe the constant is wrong, file an issue instead of bypassing the check

Example fix

// before
fetchPost("/api/filetree/copyDoc", {path: p, title: t, "notebook": "wrong-id-constant"})
// after
fetchPost("/api/filetree/copyDoc", {path: p, title: t, notebook: NOTEBOOK_ID_CONSTANT})
Defensive patterns

Strategy: validation

Validate before calling

function assertConstants(payload, constants) {
  for (const [name, expected] of Object.entries(constants)) {
    if (JSON.stringify(payload[name]) !== JSON.stringify(expected)) {
      throw new Error(`Field [${name}] must equal ${JSON.stringify(expected)}`);
    }
  }
}
assertConstants(payload, { notebook: NOTEBOOK_ID_CONSTANT });

Type guard

const isConstantMatch = (v, c) => JSON.stringify(v) === JSON.stringify(c);

Prevention

When it happens

Trigger: Calling a kernel API whose contract pins a field to a constant (via contract field metadata) and sending any other value for that field; e.g. passing a different string, number, or object to a field declared as a constant in kernel/apicontract/ definitions decoded by Decode/decodeRequestFields/avDecodeBoundFields/fileTreeBind.

Common situations: Hand-crafted fetch/curl requests built from outdated API docs; plugins hard-coding payloads copied from an older SiYuan version after the contract changed; copy-pasted request bodies where one field was edited but a constant field was accidentally changed too.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at kernel/apicontract/decode.go:152

				}
				if !found {
					return fmt.Errorf("Field [%s] has an invalid value", name)
				}
			}
			if strings.HasPrefix(option, "const=") {
				var expected, actual any
				if err := json.Unmarshal([]byte(strings.TrimPrefix(option, "const=")), &expected); err != nil {
					return err
				}
				data, err := json.Marshal(value.Field(i).Interface())
				if err != nil {
					return err
				}
				if err := json.Unmarshal(data, &actual); err != nil {
					return err
				}
				if !reflect.DeepEqual(expected, actual) {
					return fmt.Errorf("Field [%s] has an invalid constant", name)
				}
			}
		}
	}
	return nil
}

// decodeRequestValue 递归绑定复合参数,避免数组元素和嵌套字段绕过空值及必填检查。
func decodeRequestValue(raw json.RawMessage, value reflect.Value) error {
	if value.Type() == reflect.TypeFor[JSONValue]() || value.Type() == reflect.TypeFor[PublishDataValue]() {
		return json.Unmarshal(raw, value.Addr().Interface())
	}
	if bytes.Equal(bytes.TrimSpace(raw), []byte("null")) {
		switch value.Kind() {
		case reflect.Pointer, reflect.Map, reflect.Slice:
			value.SetZero()
			return nil
		default:

View on GitHub (pinned to 9f775e8a12)