{"record":{"id":"93c209c5c68c31b1","repo":"siyuan-note/siyuan","slug":"invalid-dir-path-s","errorCode":null,"errorMessage":"Invalid dir path [%s]","messagePattern":"Invalid dir path \\[(.+?)\\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/sync.go","lineNumber":625,"sourceCode":"\tlocal.Endpoint = util.NormalizeLocalPath(local.Endpoint)\n\n\tabsPath, err := filepath.Abs(local.Endpoint)\n\tif nil != err {\n\t\tmsg := fmt.Sprintf(\"get endpoint [%s] abs path failed: %s\", local.Endpoint, err)\n\t\tlogging.LogError(msg)\n\t\terr = fmt.Errorf(Conf.Language(77), msg)\n\t\treturn\n\t}\n\tif !gulu.File.IsExist(absPath) {\n\t\tmsg := fmt.Sprintf(\"endpoint [%s] not exist\", local.Endpoint)\n\t\tlogging.LogError(msg)\n\t\terr = fmt.Errorf(Conf.Language(77), msg)\n\t\treturn\n\t}\n\tif util.IsAbsPathInWorkspace(absPath) || filepath.Clean(absPath) == filepath.Clean(util.WorkspaceDir) {\n\t\tmsg := fmt.Sprintf(\"endpoint [%s] is in workspace\", local.Endpoint)\n\t\tlogging.LogError(msg)\n\t\terr = fmt.Errorf(Conf.Language(77), msg)\n\t\treturn\n\t}\n\n\tif gulu.File.IsSubPath(absPath, util.WorkspaceDir) {\n\t\tmsg := fmt.Sprintf(\"endpoint [%s] is parent of workspace\", local.Endpoint)\n\t\tlogging.LogError(msg)\n\t\terr = fmt.Errorf(Conf.Language(77), msg)\n\t\treturn\n\t}\n\n\tlocal.Timeout = util.NormalizeTimeout(local.Timeout)\n\tlocal.ConcurrentReqs = util.NormalizeConcurrentReqs(local.ConcurrentReqs, conf.ProviderLocal)\n\n\tConf.Sync.Local = local\n\tConf.Save()\n\trefreshLANSyncManager()\n\treturn\n}","sourceCodeStart":607,"sourceCodeEnd":643,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/afa823b6b4e4f183511e0bc0a3be93caa94c7c97/kernel/model/sync.go#L607-L643","documentation":"SetSyncProviderLocal reports 'endpoint [x] is in workspace' wrapped in i18n key 77 when util.IsAbsPathInWorkspace(absPath) is true or the endpoint equals the workspace directory itself. Using the workspace (or a folder inside it) as the sync target would make the sync directory contain the very data being synced, so the setting is refused before Conf is saved.","triggerScenarios":"SetSyncProviderLocal with an endpoint that resolves under the workspace directory, or exactly to the workspace directory.","commonSituations":"Pointing sync at ~/SiYuan to 'keep everything together'; selecting the workspace folder through the directory picker.","solutions":["Choose a directory outside the workspace, for example a sibling folder like ~/SiYuanSync","Create a dedicated top-level folder on the same volume and use it as the endpoint"],"exampleFix":"// before\nlocal.Endpoint = \"/home/user/SiYuan\" // the workspace itself\n// after\nlocal.Endpoint = \"/home/user/SiYuanSync\"","handlingStrategy":"validation","validationCode":"abs, _ := filepath.Abs(util.NormalizeLocalPath(local.Endpoint))\nif util.IsAbsPathInWorkspace(abs) || filepath.Clean(abs) == filepath.Clean(util.WorkspaceDir) {\n\treturn errors.New(\"endpoint must be outside the workspace\")\n}\nmodel.SetSyncProviderLocal(local)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use a dedicated sibling folder like ~/SiYuanSync as the local sync endpoint","Never select the workspace folder in the directory picker for sync"],"tags":["sync","local-provider","workspace","path-validation"],"backgroundTag":"path-inside-workspace-forbidden","analyzedSha":"afa823b6b4e4f183511e0bc0a3be93caa94c7c97","analyzedAt":"2026-08-18T17:04:10.865Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}