{"record":{"id":"0aae26a4799f5bfa","repo":"siyuan-note/siyuan","slug":"obsidian-vault-config-directory-is-missing","errorCode":null,"errorMessage":"Obsidian Vault config directory is missing","messagePattern":"Obsidian Vault config directory is missing","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/import_obsidian.go","lineNumber":233,"sourceCode":"\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) {\n\t\t\t\tobsidianTasksMu.Unlock()\n\t\t\t\treturn nil, errors.New(Conf.Language(329))\n\t\t\t}","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/import_obsidian.go#L215-L251","documentation":"`errObsidianVaultConfigMissing` is returned when the Vault root exists but its `.obsidian` configuration directory does not (`os.IsNotExist`), i.e. the folder is not actually an Obsidian Vault. It maps to i18n key 339. Other stat errors are wrapped as `errObsidianVaultUnreadable` instead.","triggerScenarios":"`validateObsidianVaultRoot` stats `<vault>/.obsidian` and gets a not-exist error — the chosen folder has no `.obsidian` subdirectory.","commonSituations":"User selected a plain folder of Markdown files never opened in Obsidian; the `.obsidian` folder was deleted/ignored by a sync tool (dotfolder excluded); user picked a parent folder above the actual vault.","solutions":["Select the actual Vault root — the folder whose `.obsidian` subdirectory exists","If `.obsidian` was removed by sync/backup exclusions, restore it (reopening the vault in Obsidian recreates it)","Verify with a file browser that `<chosenPath>/.obsidian` exists before importing"],"exampleFix":"// before\nvalidateObsidianVaultRoot(\"/home/user/plain-notes\") // no .obsidian -> errObsidianVaultConfigMissing\n// after\nvalidateObsidianVaultRoot(\"/home/user/MyVault\") // contains .obsidian/","handlingStrategy":"validation","validationCode":"try {\n  await fs.access(path.join(vaultPath, \".obsidian\"));\n} catch {\n  throw new Error(`'${vaultPath}' has no .obsidian directory — not an Obsidian Vault`);\n}","typeGuard":"function hasObsidianConfig(entries: string[]): boolean {\n  return entries.includes(\".obsidian\");\n}","tryCatchPattern":"try {\n  await api.importObsidianVault(vaultPath);\n} catch (e) {\n  if (isVaultConfigMissing(e)) {\n    // guide user to select the real vault root (folder containing .obsidian)\n  }\n}","preventionTips":["Check that <vault>/.obsidian exists before calling the API","Configure sync tools to include dotfolders so .obsidian is not dropped","Reopen the folder in Obsidian once to generate .obsidian if it was deleted"],"tags":["obsidian","import","validation","config"],"backgroundTag":"directory-not-found","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"}