siyuan-note/siyuan · error

Field [srcs]: path must not be empty

Error message

Field [srcs]: path must not be empty

What it means

This error comes from the kernel's contract decoder for the copy-files style API (decodeCopyFiles). After JSON decoding, each element of the 'srcs' array is trimmed and validated; if a resulting path is an empty string the decoder rejects the whole request. The library enforces this because copying a file with an empty source path is meaningless and would otherwise be passed down to filesystem operations.

Solutions

  1. Remove empty or whitespace-only strings from the srcs array before sending the request
  2. Check the loop that builds srcs on the client and skip blank inputs
  3. If a blank entry is meaningful, supply the correct path instead of omitting it

Example fix

// before
fetchPost("/api/filetree/copyFiles", { srcs: ["/nb/a.sy", ""] });
// after
const srcs = ["/nb/a.sy", ""].map(s => s.trim()).filter(s => s.length > 0);
fetchPost("/api/filetree/copyFiles", { srcs });
Defensive patterns

Strategy: validation

Validate before calling

const srcs = (payload.srcs || []).map(s => String(s ?? "").trim()).filter(s => s.length > 0);
if (srcs.length === 0) throw new Error("srcs must contain at least one non-empty path");

Type guard

const isValidSrcs = (v) => Array.isArray(v) && v.length > 0 && v.every(s => typeof s === "string" && s.trim() !== "");

Prevention

When it happens

Trigger: Calling an API whose body contains a 'srcs' array where at least one element is "", or a whitespace-only string like " " that trims to empty. Example: POST with {"srcs":["/data/notebook/a.sy", ""]}.

Common situations: Client-side list building that appends empty entries from blank form fields or split("\n") on trailing newlines; batch scripts generated from spreadsheets with blank rows; joining paths where the base was empty.

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


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/ec9347a67d8ce340. Report an issue: GitHub.

Appendix: source

Thrown at kernel/apicontract/file_input.go:35

	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)
	}
	return
}

func init() {
	GlobalCopyFiles.decodeRequest = func(reader io.Reader) (CopyFilesRequest, error) {
		return decodeCopyFiles(reader, "/api/file/globalCopyFiles", false)
	}
	WorkspaceCopyFiles.decodeRequest = func(reader io.Reader) (CopyFilesRequest, error) {
		return decodeCopyFiles(reader, "/api/file/workspaceCopyFiles", true)
	}
}

View on GitHub (pinned to 9f775e8a12)