siyuan-note/siyuan · error

Field [name] must not be empty

Error message

Field [name] must not be empty

What it means

decodeName backs POST /api/sync/setCloudSyncDir, /createCloudSyncDirWithGuid, and /removeCloudSyncDir. After successfully reading `name` as a string it trims whitespace; if nothing remains it returns this error. An empty or whitespace-only cloud sync directory name is not a valid identifier for a remote directory.

Solutions

  1. Provide a non-empty directory name, e.g. {"name":"my-sync-dir"}
  2. Trim client-side and reject empty input before the call
  3. List existing dirs via /api/sync/listCloudSyncDir to pick a valid name

Example fix

// before
{"name": "   "}
// after
{"name": "my-sync-dir"}
Defensive patterns

Strategy: validation

Validate before calling

const name = (p.name || '').trim(); if (!name) throw new Error('cloud sync dir name is required');

Type guard

const isNonEmptyName = (v) => typeof v === 'string' && v.trim().length > 0;

Try / catch

const res = await fetchPost('/api/sync/setCloudSyncDir', {name}); if (res.code !== 0) console.error(res.msg);

Prevention

When it happens

Trigger: POSTing {"name":""} or {"name":" "} to setCloudSyncDir/createCloudSyncDirWithGuid/removeCloudSyncDir.

Common situations: A settings dialog saving before the user typed a directory name; a script whose name variable defaulted to an empty string; copying a payload example and leaving the placeholder blank.

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/ef1671cf692f25f7. Report an issue: GitHub.

Appendix: source

Thrown at kernel/apicontract/sync.go:204

	SetSyncMode.decodeRequest = decodeMode(SetSyncMode.definition.Path)
	SetSyncAssetDownloadMode.decodeRequest = decodeMode(SetSyncAssetDownloadMode.definition.Path)
	SetSyncProvider.decodeRequest = func(reader io.Reader) (r SyncProviderRequest, err error) {
		fields, err := syncRequestFields(reader, SetSyncProvider.definition.Path)
		if err == nil {
			r.Provider, err = legacyField[float64](fields, "provider", "Number", true)
		}
		return r, err
	}
	decodeName := func(path string) func(io.Reader) (SyncNameRequest, error) {
		return func(reader io.Reader) (r SyncNameRequest, err error) {
			fields, err := syncRequestFields(reader, path)
			if err == nil {
				r.Name, err = legacyField[string](fields, "name", "String", true)
			}
			if err == nil {
				r.Name = strings.TrimSpace(r.Name)
				if r.Name == "" {
					err = errors.New("Field [name] must not be empty")
				}
			}
			return r, err
		}
	}
	SetCloudSyncDir.decodeRequest = decodeName(SetCloudSyncDir.definition.Path)
	CreateCloudSyncDir.decodeRequest = decodeName(CreateCloudSyncDir.definition.Path)
	RemoveCloudSyncDir.decodeRequest = decodeName(RemoveCloudSyncDir.definition.Path)
	SetSyncLAN.decodeRequest = func(reader io.Reader) (r SyncLANRequest, err error) {
		fields, err := syncRequestFields(reader, SetSyncLAN.definition.Path)
		if err != nil {
			return r, err
		}
		if r.Enabled, err = legacyField[bool](fields, "enabled", "Boolean", true); err != nil {
			return r, err
		}
		r.MaxConcurrentReqs, err = legacyField[float64](fields, "maxConcurrentReqs", "Number", false)
		return r, err

View on GitHub (pinned to 9f775e8a12)