{"record":{"id":"e08e898a1501fc44","repo":"siyuan-note/siyuan","slug":"w-normalize-vault-path-v-wrapped-obsidian-vault-is","errorCode":null,"errorMessage":"%w: normalize Vault path: %v (wrapped: Obsidian Vault is unreadable)","messagePattern":"%w: normalize Vault path: (.+?) \\(wrapped: Obsidian Vault is unreadable\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/import_obsidian.go","lineNumber":564,"sourceCode":"\t\tret.ImportAssets[key] = asset\n\t\tret.Analysis.ImportableAssetCount++\n\t\tret.Analysis.ImportableAssetSize += asset.Source.Size\n\t}\n\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}","sourceCodeStart":546,"sourceCodeEnd":582,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/import_obsidian.go#L546-L582","documentation":"validateObsidianVaultRoot wraps errObsidianVaultUnreadable with 'normalize Vault path: %v' when filepath.Abs(filepath.Clean(localPath)) fails. filepath.Abs essentially only fails when resolving the working directory fails (e.g. the process cwd was deleted), so this indicates a broken process environment rather than a user mistake.","triggerScenarios":"Calling the analyze/import API when the kernel process's current working directory has been removed, making Getwd (used by filepath.Abs for relative paths) fail.","commonSituations":"Kernel launched from a directory that was deleted or unmounted afterwards; containers with volatile workdirs; running on a removed network share.","solutions":["Restart the SiYuan kernel from a valid existing working directory","Pass an absolute vault path instead of a relative one so Abs has less to resolve","Check the mount/disk holding the kernel's cwd and restore it"],"exampleFix":"// before\nanalyzeVault({ localPath: '../vaults/notes' });\n// after\nanalyzeVault({ localPath: '/home/user/Documents/vaults/notes' }); // absolute path","handlingStrategy":"fallback","validationCode":"try { process.cwd(); } catch { alert('Working directory is gone; restart the kernel'); }","typeGuard":null,"tryCatchPattern":"try { await analyzeVault(opts); } catch (e) { if (isVaultUnreadable(e) && /normalize Vault path/.test(String(e))) restartKernelThenRetry(); else throw e; }","preventionTips":["Launch the kernel from a stable, existing directory","Always pass absolute vault paths","Avoid deleting or unmounting the directory the kernel was started from"],"tags":["obsidian","filesystem","path-resolution","environment"],"backgroundTag":"invalid-argument-format","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"}