siyuan-note/siyuan · error

Field [ ] is required

Error message

Field [%s] is required

What it means

A request field whose json tag does not carry the 'optional' api option must be present in the decoded body. If the key is missing from the JSON object entirely, Decode rejects the request naming the field. This enforces required fields declared by the contract.

Solutions

  1. Add the missing field with a valid value to the request body
  2. If the field is genuinely optional, add `optional` to its api tag in the contract
  3. Check the endpoint's contract definition (or generated schema) for the exact required field name and type

Example fix

// before
fetchPost("/api/filetree/renameDoc", {notebook: nb})
// after
fetchPost("/api/filetree/renameDoc", {notebook: nb, path: "/20240101120000-abc.sy"})
Defensive patterns

Strategy: validation

Validate before calling

function requireFields(body, required) {
  const missing = required.filter(k => !(k in body))
  if (missing.length) throw new Error(`Missing required fields: ${missing.join(", ")}`)
  return true
}
// requireFields(payload, ["id", "path"]) before calling the endpoint

Type guard

function hasField<T, K extends keyof T>(obj: T, key: K): obj is T & Required<Pick<T, K>> { return key in obj }

Try / catch

try { await fetchPost(path, payload) } catch (e) { const m = e.message.match(/Field \[(.+?)\] is required/); if (m) { console.error(`Add required field "${m[1]}" to request for ${path}`); return } throw e }

Prevention

When it happens

Trigger: POSTing to a contract endpoint while omitting a field tagged `api:"..."` without 'optional' — e.g. missing "id" in a block-update request or missing "path" in a file-tree operation.

Common situations: Older clients not sending fields added in newer contract versions; frontend code constructing partial payloads; plugin authors guessing at the request shape; null being sent when the field must be a concrete value (that would hit must-not-be-null instead).

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/6348082136b8bffa. Report an issue: GitHub.

Appendix: source

Thrown at kernel/apicontract/decode.go:73

			continue
		}
		if field.Anonymous && name == "" {
			if field.Type.Kind() != reflect.Struct {
				return fmt.Errorf("unsupported embedded request field: %s", field.Name)
			}
			if err := decodeRequestFields(value.Field(i), fields); err != nil {
				return err
			}
			continue
		}
		options := "," + field.Tag.Get("api") + ","
		has := func(option string) bool { return strings.Contains(options, ","+option+",") }
		raw, present := fields[name]
		if !present {
			if has("optional") {
				continue
			}
			return fmt.Errorf("Field [%s] is required", name)
		}
		isNull := bytes.Equal(bytes.TrimSpace(raw), []byte("null"))
		if isNull && !has("nullable") && field.Type.Kind() != reflect.Pointer && !has("filterstrings") {
			return fmt.Errorf("Field [%s] must not be null", name)
		}
		if has("filterstrings") {
			var entries []json.RawMessage
			if json.Unmarshal(raw, &entries) == nil {
				var ids []string
				for _, entry := range entries {
					var id string
					if !bytes.Equal(bytes.TrimSpace(entry), []byte("null")) && json.Unmarshal(entry, &id) == nil {
						ids = append(ids, id)
					}
				}
				value.Field(i).Set(reflect.ValueOf(ids))
			}
			continue

View on GitHub (pinned to 9f775e8a12)