{"record":{"id":"eeb6c41084a3d2df","repo":"siyuan-note/siyuan","slug":"field-level-should-be-of-type-number","errorCode":null,"errorMessage":"Field [level] should be of type [Number]","messagePattern":"Field \\[level\\] should be of type \\[Number\\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/apicontract/block_remaining.go","lineNumber":159,"sourceCode":"\t\treturn request, errors.New(\"Field [notebook] is required\")\n\t}\n\tif request.Scope == \"notebook\" {\n\t\trequest.Notebook = strings.TrimSpace(request.Notebook)\n\t\tif request.Notebook == \"\" {\n\t\t\treturn request, errors.New(\"Field [notebook] must not be empty\")\n\t\t}\n\t}\n\t_ = json.Unmarshal(fields[\"id\"], &request.ID)\n\treturn\n}\n\nfunc decodeHeadingLevel(reader io.Reader) (request HeadingLevelRequest, err error) {\n\tfields, err := blockRequestFields(reader, \"/api/block/getHeadingLevelTransaction\")\n\tif err != nil {\n\t\treturn request, err\n\t}\n\tif len(fields[\"level\"]) == 0 || bytes.Equal(fields[\"level\"], []byte(\"null\")) || json.Unmarshal(fields[\"level\"], &request.Level) != nil {\n\t\treturn request, errors.New(\"Field [level] should be of type [Number]\")\n\t}\n\tvar entries []json.RawMessage\n\tif raw := fields[\"ids\"]; len(raw) > 0 && !bytes.Equal(raw, []byte(\"null\")) && json.Unmarshal(raw, &entries) == nil {\n\t\trequest.IDs = []string{}\n\t\tseen := map[string]bool{}\n\t\tfor _, entry := range entries {\n\t\t\tvar id string\n\t\t\tif bytes.Equal(entry, []byte(\"null\")) || json.Unmarshal(entry, &id) != nil {\n\t\t\t\treturn request, errors.New(\"Field [ids] should contain strings\")\n\t\t\t}\n\t\t\tif !seen[id] {\n\t\t\t\trequest.IDs = append(request.IDs, id)\n\t\t\t\tseen[id] = true\n\t\t\t}\n\t\t}\n\t} else if len(fields[\"id\"]) == 0 || bytes.Equal(fields[\"id\"], []byte(\"null\")) || json.Unmarshal(fields[\"id\"], &request.ID) != nil {\n\t\treturn request, errors.New(\"Field [id] should be of type [String]\")\n\t}","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/apicontract/block_remaining.go#L141-L177","documentation":"The /api/block/getHeadingLevelTransaction request requires a numeric level field. The kernel returns this error when level is missing, an explicit null, or not a JSON number (string, boolean, object). The level selects the target heading level for the heading-conversion transaction.","triggerScenarios":"POST /api/block/getHeadingLevelTransaction with {\"ids\":[...]} but no level; \"level\":\"2\" (string instead of number); \"level\":null.","commonSituations":"Dropdown UI binding the level as a string option value; omitting level because older examples only showed ids; JSON forms serializing numeric inputs as strings.","solutions":["Send level as a JSON number: \"level\": 2 (1-6 for heading levels)","Convert string input with Number(level) before building the payload","Always include level in the payload alongside ids or id"],"exampleFix":"// before\n{ \"ids\": [\"20240101120000-abcdefg\"], \"level\": \"3\" }\n// after\n{ \"ids\": [\"20240101120000-abcdefg\"], \"level\": 3 }","handlingStrategy":"validation","validationCode":"const levelNum = Number(level);\nif (!Number.isFinite(levelNum)) throw new TypeError('level must be a number');\npayload.level = levelNum;","typeGuard":"const isHeadingLevel = (v) => typeof v === 'number' && Number.isInteger(v) && v >= 1 && v <= 6;","tryCatchPattern":"try { await fetchPost('/api/block/getHeadingLevelTransaction', payload); } catch (e) { if (/Field \\[level\\] should be of type \\[Number\\]/.test(e?.message)) { payload.level = Number(payload.level); /* retry */ } }","preventionTips":["Send level as a JSON number, never a quoted string","Coerce dropdown/select values with Number() before building the payload","Type level as number in the request interface to catch this at compile time"],"tags":["api","validation","type-mismatch"],"backgroundTag":"type-mismatch","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"}