siyuan-note/siyuan · error
Field [ ] must not be empty
Error message
Field [%s] must not be empty
What it means
For /api/block/checkBlockRef, required array fields (ids under scope "blocks", paths under scope "documents") must contain at least one element. The kernel decodes the array successfully but rejects it with this error when the nonempty requirement applies and the array length is zero. Optional fields (exactIDs, deletedIDs) are exempt from this check.
Solutions
- Ensure ids (or paths for scope "documents") contains at least one valid block/document ID before calling
- Skip the API call entirely when the caller's selection is empty
- If checking optional subsets, move those IDs into exactIDs/deletedIDs and keep ids populated
Example fix
// before
await fetchPost("/api/block/checkBlockRef", { scope: "blocks", ids: [] });
// after
if (ids.length > 0) {
await fetchPost("/api/block/checkBlockRef", { scope: "blocks", ids });
} Defensive patterns
Strategy: validation
Validate before calling
if (payload.ids.length === 0) return; // nothing to check
await fetchPost('/api/block/checkBlockRef', payload); Type guard
const hasTargets = (p) => Array.isArray(p.ids) && p.ids.length > 0;
Try / catch
try { await fetchPost('/api/block/checkBlockRef', payload); } catch (e) { if (/must not be empty/.test(e?.message)) return null; throw e; } Prevention
- Early-return when the selection list is empty before issuing the request
- Never pass through filtered results without a length check
- Document that ids/paths are required and non-empty for their scopes
When it happens
Trigger: POST /api/block/checkBlockRef with scope "blocks" and "ids": [], or scope "documents" with "paths": []. Passing "ids": [] while relying on the default scope (which defaults to "blocks") also triggers it.
Common situations: Filtering a block list produced an empty selection that was passed through unchanged; upstream code collected matching IDs into an array that ended up empty; automations that call the check endpoint unconditionally before any selection exists.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- Field [srcs] must not be empty
- Field [transactions] must not be empty
- AI editor action must not be empty
- block [ ] type is locked: expected , got
- block swap requires two non-document blocks
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/fb63a428ec776dfe.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/apicontract/block_remaining.go:92
}
}
if strings.TrimSpace(request.Scope) == "" {
request.Scope = "blocks"
}
readArray := func(key string, required, nonempty bool) ([]string, error) {
raw, present := fields[key]
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 {View on GitHub (pinned to 9f775e8a12)