{"record":{"id":"ef1671cf692f25f7","repo":"siyuan-note/siyuan","slug":"field-name-must-not-be-empty","errorCode":null,"errorMessage":"Field [name] must not be empty","messagePattern":"Field \\[name\\] must not be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/apicontract/sync.go","lineNumber":204,"sourceCode":"\tSetSyncMode.decodeRequest = decodeMode(SetSyncMode.definition.Path)\n\tSetSyncAssetDownloadMode.decodeRequest = decodeMode(SetSyncAssetDownloadMode.definition.Path)\n\tSetSyncProvider.decodeRequest = func(reader io.Reader) (r SyncProviderRequest, err error) {\n\t\tfields, err := syncRequestFields(reader, SetSyncProvider.definition.Path)\n\t\tif err == nil {\n\t\t\tr.Provider, err = legacyField[float64](fields, \"provider\", \"Number\", true)\n\t\t}\n\t\treturn r, err\n\t}\n\tdecodeName := func(path string) func(io.Reader) (SyncNameRequest, error) {\n\t\treturn func(reader io.Reader) (r SyncNameRequest, err error) {\n\t\t\tfields, err := syncRequestFields(reader, path)\n\t\t\tif err == nil {\n\t\t\t\tr.Name, err = legacyField[string](fields, \"name\", \"String\", true)\n\t\t\t}\n\t\t\tif err == nil {\n\t\t\t\tr.Name = strings.TrimSpace(r.Name)\n\t\t\t\tif r.Name == \"\" {\n\t\t\t\t\terr = errors.New(\"Field [name] must not be empty\")\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn r, err\n\t\t}\n\t}\n\tSetCloudSyncDir.decodeRequest = decodeName(SetCloudSyncDir.definition.Path)\n\tCreateCloudSyncDir.decodeRequest = decodeName(CreateCloudSyncDir.definition.Path)\n\tRemoveCloudSyncDir.decodeRequest = decodeName(RemoveCloudSyncDir.definition.Path)\n\tSetSyncLAN.decodeRequest = func(reader io.Reader) (r SyncLANRequest, err error) {\n\t\tfields, err := syncRequestFields(reader, SetSyncLAN.definition.Path)\n\t\tif err != nil {\n\t\t\treturn r, err\n\t\t}\n\t\tif r.Enabled, err = legacyField[bool](fields, \"enabled\", \"Boolean\", true); err != nil {\n\t\t\treturn r, err\n\t\t}\n\t\tr.MaxConcurrentReqs, err = legacyField[float64](fields, \"maxConcurrentReqs\", \"Number\", false)\n\t\treturn r, err","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/apicontract/sync.go#L186-L222","documentation":"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.","triggerScenarios":"POSTing {\"name\":\"\"} or {\"name\":\"   \"} to setCloudSyncDir/createCloudSyncDirWithGuid/removeCloudSyncDir.","commonSituations":"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.","solutions":["Provide a non-empty directory name, e.g. {\"name\":\"my-sync-dir\"}","Trim client-side and reject empty input before the call","List existing dirs via /api/sync/listCloudSyncDir to pick a valid name"],"exampleFix":"// before\n{\"name\": \"   \"}\n// after\n{\"name\": \"my-sync-dir\"}","handlingStrategy":"validation","validationCode":"const name = (p.name || '').trim(); if (!name) throw new Error('cloud sync dir name is required');","typeGuard":"const isNonEmptyName = (v) => typeof v === 'string' && v.trim().length > 0;","tryCatchPattern":"const res = await fetchPost('/api/sync/setCloudSyncDir', {name}); if (res.code !== 0) console.error(res.msg);","preventionTips":["Trim and check name in the UI before submitting","Never allow empty-string defaults for sync dir names","Keep dir names free of leading/trailing whitespace"],"tags":["sync","validation","http-api","empty-string"],"backgroundTag":"empty-required-field","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}