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
- Send one of the exact enum choices declared in the contract's api tag (check spelling and case)
- Update the client to use the generated enum constants from the contract schema
- If a new value is legitimately needed, extend the contract's enum option and regenerate the schema
- 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
- Import enum constants from the generated schema instead of inlining strings
- When the contract enum grows, regenerate the client before using new values
- Never send localized/display values where internal codes are expected
- Match enum values exactly, including case
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
- createEmptyParagraph must be a boolean
- ErrInvalidColumnAlign
- Field [mode] must be 0 or 1
- Field [ ] has an invalid type
- Field [ ] is required
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)