{"record":{"id":"09e8927b7c2fd480","repo":"siyuan-note/siyuan","slug":"field-groups-d-should-be-of-type-string","errorCode":null,"errorMessage":"Field [groups.%d] should be of type [String]","messagePattern":"Field \\[groups\\.(.+?)\\] should be of type \\[String\\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/apicontract/clipboard_input.go","lineNumber":68,"sourceCode":"\t\tif err != nil {\n\t\t\treturn request, err\n\t\t}\n\t\trequest.Batch = strings.TrimSpace(request.Batch)\n\t\tif request.Batch == \"\" {\n\t\t\treturn request, fmt.Errorf(\"Field [batch] must not be empty\")\n\t\t}\n\t\tgroups, err := legacyField[[]json.RawMessage](fields, \"groups\", \"Array\", true)\n\t\tif err != nil {\n\t\t\treturn request, err\n\t\t}\n\t\trequest.Groups = make([]string, 0, len(groups))\n\t\tif len(groups) == 0 {\n\t\t\treturn request, fmt.Errorf(\"Field [groups] must not be empty\")\n\t\t}\n\t\tfor i, raw := range groups {\n\t\t\tvar group string\n\t\t\tif bytes.Equal(raw, []byte(\"null\")) || json.Unmarshal(raw, &group) != nil {\n\t\t\t\treturn request, fmt.Errorf(\"Field [groups.%d] should be of type [String]\", i)\n\t\t\t}\n\t\t\trequest.Groups = append(request.Groups, group)\n\t\t}\n\t\treturn\n\t}\n}\n","sourceCodeStart":50,"sourceCodeEnd":75,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/apicontract/clipboard_input.go#L50-L75","documentation":"Request-validation error for the clipboard batch-input API: the element at index %d of the groups array is not a JSON string (null or another type), so the batch groups payload is malformed and the request is rejected before processing.","triggerScenarios":"Sending {\"groups\":[null]}, {\"groups\":[123]}, or {\"groups\":[{\"id\":\"g1\"}]} to /api/clipboard/cleanupRichText instead of an array of plain strings.","commonSituations":"Group objects serialized instead of their ID strings (missing .map(g => g.id)); null entries introduced by sparse arrays or failed lookups; mixing numeric group indexes with string IDs after a schema change.","solutions":["Send group identifiers as plain strings, e.g. groups: [\"g1\", \"g2\"]","Map object arrays to their ID strings before sending (groups.map(g => g.id))","Filter out null/undefined entries before serializing the payload"],"exampleFix":"// before\n{groups: [{id: \"g1\"}]}\n// after\n{groups: [\"g1\"]}","handlingStrategy":"type-guard","validationCode":"const isStringArray = (g) => Array.isArray(g) && g.every((x) => typeof x === 'string' && x !== null);","typeGuard":"const isStringArray = (v) => Array.isArray(v) && v.every((x) => typeof x === 'string');","tryCatchPattern":null,"preventionTips":["Map group objects to ID strings before sending","Filter null/undefined entries from the array","Avoid sparse arrays when building groups"],"tags":["validation","type-mismatch","clipboard"],"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"}