{"record":{"id":"01a3b9ce0dd0b043","repo":"siyuan-note/siyuan","slug":"obsidian-vault-is-unreadable-read-vault-root-v","errorCode":null,"errorMessage":"Obsidian Vault is unreadable: read Vault root: %v","messagePattern":"Obsidian Vault is unreadable: read Vault root: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/import_obsidian.go","lineNumber":568,"sourceCode":"\tret.Analysis.UnreferencedFileCount = len(ret.ImportAssets) - len(ret.ReferencedAssets)\n\tif ret.Analysis.UnreferencedFileCount < 0 {\n\t\tret.Analysis.UnreferencedFileCount = 0\n\t}\n\tprogress(100, \"Analysis completed\")\n\treturn ret, nil\n}\n\nfunc validateObsidianVaultRoot(localPath string) (string, error) {\n\tif strings.TrimSpace(localPath) == \"\" {\n\t\treturn \"\", fmt.Errorf(\"%w: path is empty\", errObsidianVaultUnreadable)\n\t}\n\tabs, err := filepath.Abs(filepath.Clean(localPath))\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"%w: normalize Vault path: %v\", errObsidianVaultUnreadable, err)\n\t}\n\tinfo, err := os.Lstat(abs)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"%w: read Vault root: %v\", errObsidianVaultUnreadable, err)\n\t}\n\tif !info.IsDir() {\n\t\treturn \"\", errObsidianVaultNotDirectory\n\t}\n\tif info.Mode()&os.ModeSymlink != 0 || isObsidianResolvedLink(abs) {\n\t\treturn \"\", fmt.Errorf(\"%w: Vault root is a symbolic link or reparse point\", errObsidianVaultUnsafePath)\n\t}\n\tif util.IsSensitivePath(abs) {\n\t\treturn \"\", fmt.Errorf(\"%w: selected Vault path is sensitive\", errObsidianVaultUnsafePath)\n\t}\n\tworkspace, _ := filepath.Abs(filepath.Clean(util.WorkspaceDir))\n\tif sameObsidianPath(abs, workspace) || gulu.File.IsSubPath(workspace, abs) || gulu.File.IsSubPath(abs, workspace) {\n\t\treturn \"\", fmt.Errorf(\"%w: Vault root and SiYuan workspace contain each other\", errObsidianVaultUnsafePath)\n\t}\n\tconfigPath := filepath.Join(abs, \".obsidian\")\n\tconfigInfo, statErr := os.Lstat(configPath)\n\tif statErr != nil {\n\t\tif os.IsNotExist(statErr) {","sourceCodeStart":550,"sourceCodeEnd":586,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/import_obsidian.go#L550-L586","documentation":"A wrapped variant of errObsidianVaultUnreadable (line 566-568): returned when os.Lstat(abs) fails on the resolved Vault root path. This means the path does not exist, is permission-denied, or otherwise cannot be stat'd by the OS. The error wraps the unreadable sentinel with ': read Vault root: <os error>'.","triggerScenarios":"POST /api/import/startObsidianVaultAnalysis with a localPath that resolves to a non-existent path, or a path the SiYuan process lacks permission to stat. os.Lstat returns a non-nil err and the guard fires.","commonSituations":"The Vault was moved/deleted/renamed between selection and the API call; a typo in the path; permissions deny the SiYuan process access; a network share is offline; on mobile/sandboxed environments the path is outside the accessible scope.","solutions":["Confirm the directory exists at the exact path passed to the API (check for typos, case sensitivity on Linux).","Verify the SiYuan process has read/list permissions on the path and all parent directories.","If the Vault is on a network/removable share, ensure it is mounted and accessible, then retry.","Re-select the folder via the UI picker to capture the correct, current path."],"exampleFix":"// before: vault moved or mistyped\nlocalPath := \"/home/user/MyVualt\" // typo\n// -> \"Obsidian Vault is unreadable: read Vault root: no such file or directory\"\n\n// after\nlocalPath := \"/home/user/MyVault\"","handlingStrategy":"validation","validationCode":"// Stat the path to confirm it exists and is accessible\nif _, err := os.Lstat(localPath); err != nil {\n    return fmt.Errorf(\"Vault path is not accessible: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if _, err := model.StartObsidianVaultAnalysis(localPath); err != nil {\n    if errors.Is(err, errObsidianVaultUnreadable) && strings.Contains(err.Error(), \"read Vault root\") {\n        return errors.New(\"the Vault folder does not exist or is not accessible; check the path and permissions\")\n    }\n}","preventionTips":["Verify the directory exists at the exact path (case-sensitive on Linux).","Ensure the SiYuan process has read permission on the path and ancestors.","Re-select the folder in the UI if it was moved or renamed."],"tags":["obsidian","import","validation","filesystem","permissions","not-found"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}