siyuan-note/siyuan · error
Field [srcs] must not be empty
Error message
Field [srcs] must not be empty
What it means
decodeCopyFiles in kernel/apicontract/file_input.go requires the "srcs" array field to be present and contain at least one entry; an empty array fails with "Field [srcs] must not be empty". Copying files with no sources is a no-op the API refuses rather than silently succeeding.
Solutions
- Ensure srcs contains at least one path before calling the API
- Skip the API call entirely when the source list is empty client-side
- Check the selection/filter logic that builds srcs
- Include destDir alongside a non-empty srcs list as the endpoint expects both
Example fix
// before
fetchPost("/api/file/copyFiles", { srcs: [], destDir })
// after
if (!srcs.length) return; fetchPost("/api/file/copyFiles", { srcs, destDir }) Defensive patterns
Strategy: validation
Validate before calling
function requireNonEmptySrcs(srcs) {
if (!Array.isArray(srcs) || srcs.length === 0) throw new Error("srcs must contain at least one path");
}
requireNonEmptySrcs(srcs); Type guard
const hasSrcs = (p) => Array.isArray(p.srcs) && p.srcs.length > 0;
Try / catch
try { await copyFiles({ srcs, destDir }); } catch (e) { if (String(e).includes("srcs] must not be empty")) return; /* skip empty batch */ throw e; } Prevention
- Check selection size before calling copy APIs
- Skip empty batches instead of issuing calls
- Verify the filter that builds srcs never removes everything silently
- Unit-test payload builders against empty-selection edge cases
When it happens
Trigger: Calling the copy-files API (legacyField[[]json.RawMessage] with required Array) with srcs: [] or srcs omitted-and-defaulted to empty after successful decoding.
Common situations: File manager integrations computing the source list from a selection that ended up empty; filtering out all candidate files before the call; loops that batch-copy and hit the final empty batch.
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 [ ] 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/84050f92a58171b4.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/apicontract/file_input.go:21
import (
"bytes"
"encoding/json"
"fmt"
"io"
"strings"
)
func decodeCopyFiles(reader io.Reader, path string, trim bool) (request CopyFilesRequest, err error) {
fields, err := blockRequestFields(reader, path)
if err != nil {
return request, err
}
srcs, err := legacyField[[]json.RawMessage](fields, "srcs", "Array", true)
if err != nil {
return request, err
}
if len(srcs) == 0 {
return request, fmt.Errorf("Field [srcs] must not be empty")
}
request.DestDir, err = legacyField[string](fields, "destDir", "String", true)
if err != nil {
return request, err
}
for _, raw := range srcs {
var src string
if bytes.Equal(raw, []byte("null")) || json.Unmarshal(raw, &src) != nil {
return request, fmt.Errorf("Field [srcs]: each element should be of type [String]")
}
if trim {
src = strings.TrimSpace(src)
if src == "" {
return request, fmt.Errorf("Field [srcs]: path must not be empty")
}
}
request.Srcs = append(request.Srcs, src)
}View on GitHub (pinned to 9f775e8a12)