{"record":{"id":"2a28a1e7003272ae","repo":"siyuan-note/siyuan","slug":"obsidian-vault-is-unreadable","errorCode":null,"errorMessage":"Obsidian Vault is unreadable","messagePattern":"Obsidian Vault is unreadable","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/import_obsidian.go","lineNumber":230,"sourceCode":"}\n\nfunc (err *obsidianUserError) Error() string {\n\treturn err.Cause.Error()\n}\n\nfunc (err *obsidianUserError) Unwrap() error {\n\treturn err.Cause\n}\n\nfunc newObsidianUserError(detailLanguage int, relPath string, cause error) error {\n\treturn &obsidianUserError{DetailLanguage: detailLanguage, RelPath: relPath, Cause: cause}\n}\n\nvar (\n\tobsidianTasksMu                 sync.Mutex\n\tobsidianTasks                   = map[string]*obsidianTask{}\n\tobsidianActive                  string\n\terrObsidianVaultUnreadable      = errors.New(\"Obsidian Vault is unreadable\")\n\terrObsidianVaultNotDirectory    = errors.New(\"Obsidian Vault path is not a directory\")\n\terrObsidianVaultUnsafePath      = errors.New(\"Obsidian Vault path is unsafe\")\n\terrObsidianVaultConfigMissing   = errors.New(\"Obsidian Vault config directory is missing\")\n\terrObsidianVaultMarkdownMissing = errors.New(\"Obsidian Vault has no readable Markdown\")\n\terrObsidianSourceChanged        = errors.New(\"Obsidian source file changed\")\n\n\tobsidianBlockIDPattern  = regexp.MustCompile(`(?m)(?:^|[ \\t])\\^([A-Za-z0-9-]+)[ \\t]*$`)\n\tobsidianQuotePattern    = regexp.MustCompile(`^((?:[ \\t]*>[ \\t]?)+)(.*)$`)\n\tobsidianListItemPattern = regexp.MustCompile(`^([ \\t]*(?:[-+*]|\\d+[.)])[ \\t]+)(.*)$`)\n\tobsidianFootnotePattern = regexp.MustCompile(`(?m)\\[\\^[^\\]\\r\\n]+\\]`)\n)\n\nfunc StartObsidianVaultAnalysis(localPath string) (*ObsidianVaultTask, error) {\n\tvar replacedTaskID string\n\tobsidianTasksMu.Lock()\n\tif obsidianActive != \"\" {\n\t\tif active := obsidianTasks[obsidianActive]; active != nil && !isObsidianTerminalState(active.State) {\n\t\t\tif !isObsidianPreImportState(active.State) {","sourceCodeStart":212,"sourceCodeEnd":248,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/import_obsidian.go#L212-L248","documentation":"`errObsidianVaultUnreadable` is the generic sentinel for \"the given Obsidian Vault path cannot be used\". It is wrapped with `%w` for detail (empty path, unreadable config dir) and is translated to i18n key 336 for the user via `obsidianVaultErrorLanguage`. It groups all cases where the Vault root itself could not be validated/read.","triggerScenarios":"Calling `ImportObsidianVault`/validation with an empty or whitespace-only `localPath` (`fmt.Errorf(\"%w: path is empty\", ...)`), or when the `.obsidian` config directory stat fails with a non-not-exist error (read permission/IO error), both wrapped with this sentinel.","commonSituations":"User submitted an empty vault field in the import dialog; the vault lives on an unavailable/unmounted drive or a network share that denies access; antivirus or OS permissions block reading `.obsidian`.","solutions":["Enter/re-pass a real, non-empty path to the Vault root directory (the folder containing `.obsidian`)","Check the OS permissions on the Vault directory and `.obsidian` folder and grant read access","Remount the drive/share hosting the Vault and retry"],"exampleFix":"// before\nimportObsidianVault(\"\") // wrapped: errObsidianVaultUnreadable: path is empty\n// after\nimportObsidianVault(\"/home/user/Documents/MyVault\") // real vault root containing .obsidian/","handlingStrategy":"validation","validationCode":"const stat = await fs.stat(vaultPath).catch(() => null);\nif (!stat || !stat.isDirectory()) {\n  throw new Error(\"Vault path must be an existing readable directory\");\n}\nawait fs.access(path.join(vaultPath, \".obsidian\"));","typeGuard":"function isReadableVaultPath(p: string): boolean {\n  return typeof p === \"string\" && p.trim().length > 0;\n}","tryCatchPattern":"try {\n  await api.importObsidianVault(vaultPath);\n} catch (e) {\n  if (isVaultUnreadable(e)) {\n    // surface i18n key 336 guidance: provide a real, accessible vault path\n  }\n}","preventionTips":["Never submit an empty vault path — require it in the UI beforehand","Confirm the drive/share hosting the vault is mounted and readable","Check OS permissions on the vault and its .obsidian directory"],"tags":["obsidian","import","path-validation","filesystem"],"backgroundTag":"path-is-not-a-directory","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"}