siyuan-note/siyuan · error

Field [ ] has an invalid value

Error message

Field [%s] has an invalid value

What it means

After decoding, every `enum=a|b|c` option is checked against the field's string value; if the value matches none of the pipe-separated choices the request is rejected with 'Field [x] has an invalid value'. The accepted choices live in the contract's api tag, so they are the authoritative whitelist.

Solutions

  1. Send one of the exact enum choices declared in the contract's api tag (check spelling and case)
  2. Update the client to use the generated enum constants from the contract schema
  3. If a new value is legitimately needed, extend the contract's enum option and regenerate the schema
  4. Log the received value against the enum list to identify casing/whitespace issues

Example fix

// before
fetchPost("/api/av/render", {id: avID, layout: "grid"})
// after
fetchPost("/api/av/render", {id: avID, layout: "table"})
Defensive patterns

Strategy: validation

Validate before calling

function assertEnum(payload, field, allowed) {
  const v = payload[field]
  if (v !== undefined && !allowed.includes(v)) throw new Error(`Field "${field}" must be one of: ${allowed.join(" | ")} (got "${v}")`)
}
// assertEnum(payload, "layout", ["table", "kanban", "gallery"])

Type guard

function isLayout(v: string): v is "table" | "kanban" | "gallery" { return ["table", "kanban", "gallery"].includes(v) }

Try / catch

try { await fetchPost(path, payload) } catch (e) { const m = e.message.match(/Field \[(.+?)\] has an invalid value/); if (m) { console.error(`Value for "${m[1]}" is outside the contract's enum — check allowed choices in the schema`); return } throw e }

Prevention

When it happens

Trigger: Sending layout:"unknown" to an attribute-view endpoint, sorting mode values outside the declared set, or any enum-marked field given a value not in its enum list.

Common situations: Typos or wrong casing ("Table" vs "table"); newer/older clients disagreeing on allowed values after an enum was extended; plugin authors inventing values not in the contract; localized values sent instead of internal codes.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at kernel/apicontract/decode.go:136

			if trimmed == "" {
				return fmt.Errorf("Field [%s] must not be empty", name)
			}
			value.Field(i).SetString(trimmed)
		}
		for _, option := range strings.Split(field.Tag.Get("api"), ",") {
			if strings.HasPrefix(option, "enum=") {
				if field.Type.Kind() != reflect.String {
					return fmt.Errorf("unsupported enum field: %s", name)
				}
				found := false
				for _, choice := range strings.Split(strings.TrimPrefix(option, "enum="), "|") {
					if value.Field(i).String() == choice {
						found = true
						break
					}
				}
				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)
				}
			}

View on GitHub (pinned to 9f775e8a12)