{"record":{"id":"3c0e285040a6da75","repo":"siyuan-note/siyuan","slug":"obsidian-vault-has-no-readable-markdown","errorCode":null,"errorMessage":"Obsidian Vault has no readable Markdown","messagePattern":"Obsidian Vault has no readable Markdown","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/import_obsidian.go","lineNumber":234,"sourceCode":"}\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}\n\t\t\tif active.Cancel != nil {","sourceCodeStart":216,"sourceCodeEnd":252,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/import_obsidian.go#L216-L252","documentation":"`errObsidianVaultMarkdownMissing` is returned when the Vault passes structural validation (directory, `.obsidian` present) but the walk found zero readable `.md` files. It maps to i18n key 340, telling the user there is nothing to import.","triggerScenarios":"During Vault scan, `len(mdFiles) == 0` after collecting Markdown files — no `.md` files matched, or all candidate files failed readability checks during enumeration.","commonSituations":"Vault contains only attachments/canvas/other extensions; notes were renamed to `.txt`; permissions or path filters excluded every note; an empty new vault was selected.","solutions":["Confirm the Vault actually contains `.md` notes and that they are readable by the current OS user","Rename notes with other extensions (`.txt`, `.mdown`) to `.md` inside the Vault","Choose a different Vault folder that holds the notes"],"exampleFix":"// before\n// vault with only images and .txt files\nscanObsidianVault(...) // errObsidianVaultMarkdownMissing\n// after\n// rename .txt notes to .md inside the vault, then import\nscanObsidianVault(...) // imports normally","handlingStrategy":"validation","validationCode":"const md = (await fs.readdir(vaultPath, { recursive: true }))\n  .filter(f => f.toLowerCase().endsWith(\".md\"));\nif (md.length === 0) {\n  throw new Error(\"Vault contains no .md notes; nothing to import\");\n}","typeGuard":"function hasMarkdownNotes(files: string[]): boolean {\n  return files.some(f => f.toLowerCase().endsWith(\".md\"));\n}","tryCatchPattern":"try {\n  await api.importObsidianVault(vaultPath);\n} catch (e) {\n  if (isVaultMarkdownMissing(e)) {\n    // inform user the vault has no importable Markdown and stop\n  }\n}","preventionTips":["Verify the vault contains .md notes before starting the import","Rename .txt/.mdown notes to .md inside the vault first","Check file read permissions so the vault walk can see the notes"],"tags":["obsidian","import","validation","empty-input"],"backgroundTag":"empty-result-set","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"}