siyuan-note/siyuan · error
Field [ ] should contain non-empty strings
Error message
Field [%s] should contain non-empty strings
What it means
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.
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
Example fix
// before
const ids = idList.split(","); // ["id1", ""]
await fetchPost("/api/block/checkBlockRef", { scope: "blocks", ids });
// after
const ids = idList.split(",").map(s => s.trim()).filter(Boolean);
await fetchPost("/api/block/checkBlockRef", { scope: "blocks", ids }); Defensive patterns
Strategy: validation
Validate before calling
const clean = (ids) => ids.map(s => String(s).trim()).filter(s => s.length > 0);
await fetchPost('/api/block/checkBlockRef', { scope: 'blocks', ids: clean(rawIds) }); Type guard
const allNonEmptyStrings = (arr) => Array.isArray(arr) && arr.every((x) => typeof x === 'string' && x.trim().length > 0);
Try / catch
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 */ } } Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Field [ids] should contain strings
- AI editor action must not be empty
- block [ ] type is locked: expected , got
- block swap requires two non-document blocks
- Bookmark cannot be empty
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/947943df467a0efd.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/apicontract/block_remaining.go:99
if !present && !required {
return nil, nil
}
if !present || bytes.Equal(raw, []byte("null")) {
return nil, fmt.Errorf("Field [%s] is required", key)
}
var entries []json.RawMessage
if json.Unmarshal(raw, &entries) != nil {
return nil, fmt.Errorf("Field [%s] should be of type [Array]", key)
}
if nonempty && len(entries) == 0 {
return nil, fmt.Errorf("Field [%s] must not be empty", key)
}
var values []string
seen := map[string]bool{}
for _, entry := range entries {
var value string
if json.Unmarshal(entry, &value) != nil || strings.TrimSpace(value) == "" {
return nil, fmt.Errorf("Field [%s] should contain non-empty strings", key)
}
if !seen[value] {
values = append(values, value)
seen[value] = true
}
}
return values, nil
}
switch request.Scope {
case "blocks":
if request.IDs, err = readArray("ids", true, true); err != nil {
return
}
if request.ExactIDs, err = readArray("exactIDs", false, false); err != nil {
return
}
if request.DeletedIDs, err = readArray("deletedIDs", false, false); err != nil {
returnView on GitHub (pinned to 9f775e8a12)