{"record":{"id":"cb9ce8902fd10425","repo":"siyuan-note/siyuan","slug":"field-s-has-an-invalid-value","errorCode":null,"errorMessage":"Field [%s] has an invalid value","messagePattern":"Field \\[(.+?)\\] has an invalid value","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/apicontract/decode.go","lineNumber":136,"sourceCode":"\t\t\tif trimmed == \"\" {\n\t\t\t\treturn fmt.Errorf(\"Field [%s] must not be empty\", name)\n\t\t\t}\n\t\t\tvalue.Field(i).SetString(trimmed)\n\t\t}\n\t\tfor _, option := range strings.Split(field.Tag.Get(\"api\"), \",\") {\n\t\t\tif strings.HasPrefix(option, \"enum=\") {\n\t\t\t\tif field.Type.Kind() != reflect.String {\n\t\t\t\t\treturn fmt.Errorf(\"unsupported enum field: %s\", name)\n\t\t\t\t}\n\t\t\t\tfound := false\n\t\t\t\tfor _, choice := range strings.Split(strings.TrimPrefix(option, \"enum=\"), \"|\") {\n\t\t\t\t\tif value.Field(i).String() == choice {\n\t\t\t\t\t\tfound = true\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif !found {\n\t\t\t\t\treturn fmt.Errorf(\"Field [%s] has an invalid value\", name)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif strings.HasPrefix(option, \"const=\") {\n\t\t\t\tvar expected, actual any\n\t\t\t\tif err := json.Unmarshal([]byte(strings.TrimPrefix(option, \"const=\")), &expected); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tdata, err := json.Marshal(value.Field(i).Interface())\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tif err := json.Unmarshal(data, &actual); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tif !reflect.DeepEqual(expected, actual) {\n\t\t\t\t\treturn fmt.Errorf(\"Field [%s] has an invalid constant\", name)\n\t\t\t\t}\n\t\t\t}","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/apicontract/decode.go#L118-L154","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nfetchPost(\"/api/av/render\", {id: avID, layout: \"grid\"})\n// after\nfetchPost(\"/api/av/render\", {id: avID, layout: \"table\"})","handlingStrategy":"validation","validationCode":"function assertEnum(payload, field, allowed) {\n  const v = payload[field]\n  if (v !== undefined && !allowed.includes(v)) throw new Error(`Field \"${field}\" must be one of: ${allowed.join(\" | \")} (got \"${v}\")`)\n}\n// assertEnum(payload, \"layout\", [\"table\", \"kanban\", \"gallery\"])","typeGuard":"function isLayout(v: string): v is \"table\" | \"kanban\" | \"gallery\" { return [\"table\", \"kanban\", \"gallery\"].includes(v) }","tryCatchPattern":"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 }","preventionTips":["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"],"tags":["enum","validation","api-contract","whitelist"],"backgroundTag":"invalid-enum-value","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}