siyuan-note/siyuan · error
Obsidian Vault config directory is missing
Error message
Obsidian Vault config directory is missing
What it means
A sentinel error returned when the .obsidian configuration subdirectory is missing or malformed inside the selected Vault root. validateObsidianVaultRoot stats `<vault>/.obsidian`: if it does not exist (os.IsNotExist), or if it exists but is not a directory or is itself a symlink/reparse point, this error is returned. It is also the error that distinguishes a genuine Obsidian Vault from an arbitrary Markdown folder. The obsidianVaultErrorLanguage helper maps it to i18n key 339.
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 251596fc0d)
Solutions
- Confirm the selected directory was opened in Obsidian at least once, which creates the .obsidian folder.
- If migrating/copying the Vault, ensure hidden directories are included (.obsidian is hidden by default on Unix).
- Select the immediate parent of the .obsidian folder as the Vault root — not a level above or below.
- If .obsidian is a symlink, replace it with the actual directory or point at the real Vault location.
Example fix
// before: plain md folder with no .obsidian localPath := "/home/user/just-markdown" // -> errObsidianVaultConfigMissing // after: use a real Obsidian Vault root localPath := "/home/user/MyVault" // contains /home/user/MyVault/.obsidian/
Defensive patterns
Strategy: validation
Validate before calling
// Confirm the .obsidian config directory exists and is a real directory
func ensureObsidianConfig(vaultDir string) error {
cfg := filepath.Join(vaultDir, ".obsidian")
info, err := os.Lstat(cfg)
if err != nil { return fmt.Errorf(".obsidian config missing: %w", err) }
if !info.IsDir() { return errors.New(".obsidian is not a directory") }
if info.Mode()&os.ModeSymlink != 0 { return errors.New(".obsidian is a symlink") }
return nil
} Try / catch
if _, err := model.StartObsidianVaultAnalysis(localPath); err != nil {
if errors.Is(err, errObsidianVaultConfigMissing) {
return errors.New("this folder is not an Obsidian Vault (no .obsidian config found); open it in Obsidian first")
}
} Prevention
- Open the folder in Obsidian at least once so .obsidian is created.
- When copying a Vault, include hidden files so .obsidian comes along.
- Select the folder directly containing .obsidian as the root.
When it happens
Trigger: POST /api/import/startObsidianVaultAnalysis with a directory that has no .obsidian subfolder (i.e. it is not actually an Obsidian Vault), or where .obsidian is a file/symlink rather than a real directory.
Common situations: Selecting a plain folder of Markdown files that was never opened in Obsidian; selecting a folder that was an Obsidian Vault but the .obsidian dir was deleted or not copied; .obsidian is a symlink (some sync setups symlink it); the user is confused about which folder is the Vault root and picked a parent or child.
Related errors
- Obsidian Vault is unreadable
- Obsidian Vault path is not a directory
- Obsidian Vault path is unsafe
- Obsidian Vault has no readable Markdown
- Obsidian source file changed
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/0aae26a4799f5bfa.
Report an issue: GitHub.