siyuan-note/siyuan · error

Field [srcs]: each element should be of type [String]

Error message

Field [srcs]: each element should be of type [String]

What it means

decodeCopyFiles validates each element of the "srcs" array: an element that is the JSON literal null or fails json.Unmarshal into a string causes "Field [srcs]: each element should be of type [String]". Every source must be a JSON string path; mixed-type or null entries are rejected wholesale for the request.

Solutions

  1. Make every srcs element a string path, e.g. ["/data/2023/a.sy"]
  2. Strip null/undefined/non-string entries before sending
  3. Stringify path-like values if your source of truth uses non-strings legitimately
  4. Reuse the same validated path list you use for other file APIs

Example fix

// before
srcs: ["/a.sy", null, 3]
// after
srcs: ["/a.sy"].filter(p => typeof p === "string")
Defensive patterns

Strategy: type-guard

Validate before calling

function onlyStringPaths(srcs) {
  const out = (srcs || []).filter((s) => typeof s === "string" && s.length > 0);
  if (out.length !== (srcs || []).length) throw new Error("all srcs must be non-empty strings");
  return out;
}
payload.srcs = onlyStringPaths(srcs);

Type guard

const isStringArray = (v) => Array.isArray(v) && v.every((s) => typeof s === "string");

Try / catch

try { await copyFiles(payload); } catch (e) { if (String(e).includes("each element should be of type [String]")) console.error("srcs contains non-string elements:", payload.srcs); }

Prevention

When it happens

Trigger: Calling the copy-files API with srcs like ["/a.sy", null], ["/a.sy", 42], or objects inside srcs; element bytes exactly equal to null also trigger it (note: no whitespace tolerance here, unlike other checks).

Common situations: JS arrays holding undefined serialized as null; numeric file handles/IDs passed instead of path strings; spreading objects into the srcs array by mistake.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at kernel/apicontract/file_input.go:30

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