{"record":{"id":"18849ecbf2c92329","repo":"siyuan-note/siyuan","slug":"w-read-vault-root-v","errorCode":null,"errorMessage":"%w: read Vault root: %v","messagePattern":"%w: read Vault root: (.+?)","errorType":"error_code","errorClass":"errObsidianVaultUnreadable","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/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/import_obsidian.go#L550-L586","documentation":"validateObsidianVaultRoot wraps errObsidianVaultUnreadable: reading/stat-ing the Vault root directory failed after path normalization (permissions, not a directory, or a broken symlink). The underlying os error is included in the message.","triggerScenarios":"validateObsidianVaultRoot at kernel/model/import_obsidian.go:568 when the vault root cannot be stat'ed: typo'd path, deleted folder, disconnected drive, or permission denied on a parent directory.","commonSituations":"Vault folder moved/renamed after being saved in settings; external/USB drive unplugged; network share unavailable; macOS privacy (TCC) blocking kernel access to Documents/Desktop.","solutions":["Confirm the path exists (ls/stat it) and correct the vault path if moved or renamed","Reconnect the drive or network share hosting the vault","Grant the SiYuan kernel disk-access permission if OS privacy protection blocks the path","Re-run the analysis once the path is reachable"],"exampleFix":"// before\nanalyzeObsidianVault(\"/Volumes/USB/vault\") // drive unplugged\n// after\nif _, err := os.Stat(vaultPath); err != nil {\n    return errors.New(\"vault path unreachable: \" + err.Error())\n}\nanalyzeObsidianVault(vaultPath)","handlingStrategy":"validation","validationCode":"if _, err := os.Stat(vaultPath); err != nil {\n    return fmt.Errorf(\"vault path unreachable: %w\", err)\n}","typeGuard":"null","tryCatchPattern":"_, err := AnalyzeObsidianVault(vaultPath)\nif err != nil && strings.Contains(err.Error(), \"read Vault root\") {\n    askUserToReconnectOrRepickVault()\n}","preventionTips":["Verify the vault folder exists before import","Reconnect external/network drives beforehand","Grant OS disk-access permissions to the SiYuan app for the vault location"],"tags":["obsidian-import","file-not-found","lstat","filesystem"],"backgroundTag":"file-not-found","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}