siyuan-note/siyuan · error
read Vault path [%s]: %w
Error message
read Vault path [%s]: %w
What it means
While walking the vault, `entry.Info()` failed for a path and the importer classified the path as essential (a directory, or a `.md` file), so it aborts with this error instead of silently skipping. Non-essential files whose metadata cannot be read are only recorded as analysis warnings. This surfaces filesystem-level problems that would otherwise corrupt the import inventory.
Source
Thrown at kernel/model/import_obsidian.go:623
sort.Slice(entries, func(i, j int) bool { return strings.ToLower(entries[i].Name()) < strings.ToLower(entries[j].Name()) })
for _, entry := range entries {
if err = ctx.Err(); err != nil {
return err
}
name := entry.Name()
rel := path.Join(relDir, filepath.ToSlash(name))
abs := filepath.Join(absDir, name)
if strings.HasPrefix(name, ".") {
if relDir == "" && name == ".obsidian" {
continue
}
vault.Analysis.SkippedHiddenCount++
continue
}
entryInfo, infoErr := entry.Info()
if infoErr != nil {
if entry.IsDir() || strings.EqualFold(filepath.Ext(name), ".md") {
return fmt.Errorf("read Vault path [%s]: %w", rel, infoErr)
}
vault.Analysis.Warnings = append(vault.Analysis.Warnings, rel)
continue
}
if entry.Type()&os.ModeSymlink != 0 || entryInfo.Mode()&os.ModeSymlink != 0 || isObsidianResolvedLink(abs) {
vault.Analysis.SkippedLinkCount++
continue
}
if entryInfo.IsDir() {
nestedConfig := filepath.Join(abs, ".obsidian")
if nestedInfo, nestedErr := os.Lstat(nestedConfig); nestedErr == nil {
if nestedInfo.IsDir() || nestedInfo.Mode()&os.ModeSymlink != 0 || isObsidianResolvedLink(nestedConfig) {
vault.Analysis.SkippedNestedVaultCount++
continue
}
}
if err = scanObsidianVaultFiles(ctx, vault, rel, abs); err != nil {
return errView on GitHub (pinned to 8641553a1f)
Solutions
- Identify the path from the error message and check it exists with `ls -la <vault>/<rel>`
- Fix permissions on that specific file or directory
- Pause sync clients (OneDrive/Dropbox/iCloud) during import so files are not changing
- Enable long-path support or shorten paths on Windows if MAX_PATH is the cause
Example fix
# before: file metadata unreadable ls -la vault/notes.md # permission denied # after chmod u+rw vault/notes.md
Defensive patterns
Strategy: try-catch
Validate before calling
import fs from "fs"
try { fs.statSync(mdFilePath) } catch (e) { repairOrRemove(mdFilePath) } Try / catch
try {
await importVault(vaultRoot)
} catch (e) {
if (String(e.message).includes("read Vault path")) {
const rel = e.message.match(/\[(.*?)\]/)?.[1]
console.warn(`Metadata unreadable for ${rel}; check existence and permissions`)
}
} Prevention
- Pause cloud sync (OneDrive files-on-demand, Dropbox, iCloud) during import
- Do not edit/rename notes in Obsidian while importing
- Keep note paths short on Windows to avoid MAX_PATH errors
When it happens
Trigger: During scanObsidianVaultFiles, entry.Info() returns an error for a directory entry or for a file whose extension is `.md` (case-insensitive), e.g. permission denied, entry vanished between ReadDir and Info, or long-path errors on Windows.
Common situations: A markdown file deleted or renamed by Obsidian/sync while import is running; permission changes on specific notes; cloud-sync placeholders whose metadata cannot be hydrated (e.g. OneDrive files-on-demand); Windows MAX_PATH overruns.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- %w: Vault root and SiYuan workspace contain each other
- %w: read Vault config directory: %v
- read Vault directory [%s]: %w
- Vault paths differ only by letter case [%s] and [%s]
- 346
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/2ab8d5557d952793.
Report an issue: GitHub.