siyuan-note/siyuan · error
Obsidian Vault config directory is missing
Error message
Obsidian Vault config directory is missing
What it means
`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.
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
Example fix
// before
validateObsidianVaultRoot("/home/user/plain-notes") // no .obsidian -> errObsidianVaultConfigMissing
// after
validateObsidianVaultRoot("/home/user/MyVault") // contains .obsidian/ Defensive patterns
Strategy: validation
Validate before calling
try {
await fs.access(path.join(vaultPath, ".obsidian"));
} catch {
throw new Error(`'${vaultPath}' has no .obsidian directory — not an Obsidian Vault`);
} Type guard
function hasObsidianConfig(entries: string[]): boolean {
return entries.includes(".obsidian");
} Try / catch
try {
await api.importObsidianVault(vaultPath);
} catch (e) {
if (isVaultConfigMissing(e)) {
// guide user to select the real vault root (folder containing .obsidian)
}
} Prevention
- 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
When it happens
Trigger: `validateObsidianVaultRoot` stats `<vault>/.obsidian` and gets a not-exist error — the chosen folder has no `.obsidian` subdirectory.
Common situations: 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.
Related errors
- Obsidian Vault has no readable Markdown
- 199
- 350
- Argon2id Iterations too high (maximum 10)
- Argon2id Memory too high (maximum 256 MB)
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/0aae26a4799f5bfa.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/import_obsidian.go:233
return err.Cause.Error()
}
func (err *obsidianUserError) Unwrap() error {
return err.Cause
}
func newObsidianUserError(detailLanguage int, relPath string, cause error) error {
return &obsidianUserError{DetailLanguage: detailLanguage, RelPath: relPath, Cause: cause}
}
var (
obsidianTasksMu sync.Mutex
obsidianTasks = map[string]*obsidianTask{}
obsidianActive string
errObsidianVaultUnreadable = errors.New("Obsidian Vault is unreadable")
errObsidianVaultNotDirectory = errors.New("Obsidian Vault path is not a directory")
errObsidianVaultUnsafePath = errors.New("Obsidian Vault path is unsafe")
errObsidianVaultConfigMissing = errors.New("Obsidian Vault config directory is missing")
errObsidianVaultMarkdownMissing = errors.New("Obsidian Vault has no readable Markdown")
errObsidianSourceChanged = errors.New("Obsidian source file changed")
obsidianBlockIDPattern = regexp.MustCompile(`(?m)(?:^|[ \t])\^([A-Za-z0-9-]+)[ \t]*$`)
obsidianQuotePattern = regexp.MustCompile(`^((?:[ \t]*>[ \t]?)+)(.*)$`)
obsidianListItemPattern = regexp.MustCompile(`^([ \t]*(?:[-+*]|\d+[.)])[ \t]+)(.*)$`)
obsidianFootnotePattern = regexp.MustCompile(`(?m)\[\^[^\]\r\n]+\]`)
)
func StartObsidianVaultAnalysis(localPath string) (*ObsidianVaultTask, error) {
var replacedTaskID string
obsidianTasksMu.Lock()
if obsidianActive != "" {
if active := obsidianTasks[obsidianActive]; active != nil && !isObsidianTerminalState(active.State) {
if !isObsidianPreImportState(active.State) {
obsidianTasksMu.Unlock()
return nil, errors.New(Conf.Language(329))
}View on GitHub (pinned to 9f775e8a12)