{"record":{"id":"947943df467a0efd","repo":"siyuan-note/siyuan","slug":"field-s-should-contain-non-empty-strings","errorCode":null,"errorMessage":"Field [%s] should contain non-empty strings","messagePattern":"Field \\[(.+?)\\] should contain non-empty strings","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/apicontract/block_remaining.go","lineNumber":99,"sourceCode":"\t\tif !present && !required {\n\t\t\treturn nil, nil\n\t\t}\n\t\tif !present || bytes.Equal(raw, []byte(\"null\")) {\n\t\t\treturn nil, fmt.Errorf(\"Field [%s] is required\", key)\n\t\t}\n\t\tvar entries []json.RawMessage\n\t\tif json.Unmarshal(raw, &entries) != nil {\n\t\t\treturn nil, fmt.Errorf(\"Field [%s] should be of type [Array]\", key)\n\t\t}\n\t\tif nonempty && len(entries) == 0 {\n\t\t\treturn nil, fmt.Errorf(\"Field [%s] must not be empty\", key)\n\t\t}\n\t\tvar values []string\n\t\tseen := map[string]bool{}\n\t\tfor _, entry := range entries {\n\t\t\tvar value string\n\t\t\tif json.Unmarshal(entry, &value) != nil || strings.TrimSpace(value) == \"\" {\n\t\t\t\treturn nil, fmt.Errorf(\"Field [%s] should contain non-empty strings\", key)\n\t\t\t}\n\t\t\tif !seen[value] {\n\t\t\t\tvalues = append(values, value)\n\t\t\t\tseen[value] = true\n\t\t\t}\n\t\t}\n\t\treturn values, nil\n\t}\n\tswitch request.Scope {\n\tcase \"blocks\":\n\t\tif request.IDs, err = readArray(\"ids\", true, true); err != nil {\n\t\t\treturn\n\t\t}\n\t\tif request.ExactIDs, err = readArray(\"exactIDs\", false, false); err != nil {\n\t\t\treturn\n\t\t}\n\t\tif request.DeletedIDs, err = readArray(\"deletedIDs\", false, false); err != nil {\n\t\t\treturn","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/apicontract/block_remaining.go#L81-L117","documentation":"Every element of an array field in /api/block/checkBlockRef must be a JSON string that is non-empty after trimming whitespace. The kernel rejects the request when any element is not a string (number, object, null) or is an empty/whitespace-only string. Duplicate values are tolerated and deduplicated, but blank entries are not.","triggerScenarios":"POST /api/block/checkBlockRef with \"ids\": [\"id1\", \"\"] or \"ids\": [123]; scope \"documents\" with \"paths\": [\"/\"] containing a whitespace-only entry; exactIDs/deletedIDs arrays containing null elements.","commonSituations":"Joining IDs from a textarea where a trailing comma or blank line produced an empty entry; map/filter code that kept placeholder values; null entries appearing after JSON round-trips through sparse arrays.","solutions":["Filter the array before sending: entries.every(id => typeof id === 'string' && id.trim())","Remove empty strings caused by trailing separators when splitting an ID list","Ensure every element is a JSON string, not a number or null"],"exampleFix":"// before\nconst ids = idList.split(\",\"); // [\"id1\", \"\"]\nawait fetchPost(\"/api/block/checkBlockRef\", { scope: \"blocks\", ids });\n// after\nconst ids = idList.split(\",\").map(s => s.trim()).filter(Boolean);\nawait fetchPost(\"/api/block/checkBlockRef\", { scope: \"blocks\", ids });","handlingStrategy":"validation","validationCode":"const clean = (ids) => ids.map(s => String(s).trim()).filter(s => s.length > 0);\nawait fetchPost('/api/block/checkBlockRef', { scope: 'blocks', ids: clean(rawIds) });","typeGuard":"const allNonEmptyStrings = (arr) => Array.isArray(arr) && arr.every((x) => typeof x === 'string' && x.trim().length > 0);","tryCatchPattern":"try { await fetchPost('/api/block/checkBlockRef', payload); } catch (e) { if (/should contain non-empty strings/.test(e?.message)) { payload.ids = payload.ids.filter(Boolean); /* retry */ } }","preventionTips":["Trim and filter ID arrays right after parsing user input","Avoid splitting raw text into ID arrays without filtering empty segments","Keep block IDs as strings end-to-end; never coerce to numbers"],"tags":["api","validation","array-elements"],"backgroundTag":"invalid-argument-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"}