{"record":{"id":"86881d76003d4a18","repo":"siyuan-note/siyuan","slug":"field-s-is-required-inline-style-input","errorCode":null,"errorMessage":"Field [%s] is required","messagePattern":"Field \\[(.+?)\\] is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/apicontract/inline_style_input.go","lineNumber":44,"sourceCode":"\n// legacyJSONValue 保留先解析通用 JSON 再绑定结构体时的数字归一化和大小写匹配。\nfunc legacyJSONValue[T any](raw []byte) (value T, err error) {\n\tvar normalized any\n\tif err = json.Unmarshal(raw, &normalized); err != nil {\n\t\treturn\n\t}\n\tdata, err := json.Marshal(normalized)\n\tif err == nil {\n\t\terr = json.Unmarshal(data, &value)\n\t}\n\treturn\n}\n\nfunc legacyField[T any](fields map[string]json.RawMessage, key, kind string, required bool) (value T, err error) {\n\traw := fields[key]\n\tif len(raw) == 0 || bytes.Equal(raw, []byte(\"null\")) {\n\t\tif required {\n\t\t\terr = fmt.Errorf(\"Field [%s] is required\", key)\n\t\t}\n\t\treturn\n\t}\n\tif json.Unmarshal(raw, &value) != nil {\n\t\terr = fmt.Errorf(\"Field [%s] should be of type [%s]\", key, kind)\n\t}\n\treturn\n}\n\nfunc init() {\n\tSetInlineStyles.decodeRequest = func(reader io.Reader) (request SetInlineStylesRequest, err error) {\n\t\tfields, err := blockRequestFields(reader, \"/api/storage/setInlineStyles\")\n\t\tif err != nil {\n\t\t\treturn request, err\n\t\t}\n\t\tversion, err := legacyField[float64](fields, \"version\", \"Number\", true)\n\t\tif err != nil {\n\t\t\treturn request, err","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/apicontract/inline_style_input.go#L26-L62","documentation":"legacyField is the shared legacy-request field decoder used across apicontract handlers. When a field marked required=true is absent from the fields map (zero-length raw bytes) or explicitly null, it fails with 'Field [<key>] is required'. This is the generic missing-required-field error for all endpoints still routed through legacy decoding.","triggerScenarios":"Any legacy-decoded endpoint call (SetInlineStyles, AI string params, attribute-view parsed requests, bazaar strings, copyFiles, DocVersionRef decoding, graph requests) omitting a required key or passing null for it.","commonSituations":"Hand-written scripts calling the kernel HTTP API and missing a field; older clients after a contract added a new required field; templated payloads with unfilled placeholders resolving to null.","solutions":["Add the named field (given in the message) to the request body","Replace null values for required fields with actual values","Check field name spelling and casing against the API contract docs","Update the client to the current API version if the field was recently made required"],"exampleFix":"// before\n{\"id\": \"20240101120000-abcdef1\"}\n// after\n{\"id\": \"20240101120000-abcdef1\", \"type\": \"id\"}","handlingStrategy":"validation","validationCode":"const REQUIRED = [\"id\", \"type\"];\nfor (const k of REQUIRED) {\n  if (body[k] === undefined || body[k] === null) throw new Error(`Field [${k}] is required`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  const resp = await fetch(url, {method: \"POST\", body: JSON.stringify(body)});\n  const out = await resp.json();\n} catch (e) {\n  if (String(e).includes(\"is required\")) {\n    console.error(\"Missing required field:\", e.message); // parse key from [key]\n  } else {\n    throw e;\n  }\n}","preventionTips":["Keep a per-endpoint required-field checklist and validate before send","Never send explicit null for required fields","Re-check contracts after API version upgrades"],"tags":["api","validation","missing-field","legacy"],"backgroundTag":"missing-required-argument","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"}