siyuan-note/siyuan · error
failed to read directory: %w
Error message
failed to read directory: %w
What it means
Thrown by siyuan.storage.list when os.ReadDir fails on the resolved absolute path. The OS error is wrapped with %w and rejected through the Promise. It does not fire for an empty directory (that resolves to []); only for read failures.
Source
Thrown at kernel/plugin/api_storage.go:427
err = fmt.Errorf("panic during siyuan.storage.list: %v", r)
}
p.worker.Run(func(rt *goja.Runtime) (_ any, _ error) {
if lo.IsNil(err) {
if resolveErr := resolve(result); resolveErr != nil {
logging.LogErrorf("[plugin:%s] siyuan.storage.list resolve: %v", p.Name, resolveErr)
}
} else {
if rejectErr := reject(rt.NewGoError(err)); rejectErr != nil {
logging.LogErrorf("[plugin:%s] siyuan.storage.list reject: %v", p.Name, rejectErr)
}
}
return
}, nil)
}()
entries, readErr := os.ReadDir(abs)
if readErr != nil {
err = fmt.Errorf("failed to read directory: %w", readErr)
return
}
results := make([]R, 0, len(entries))
for _, entry := range entries {
info, infoErr := entry.Info()
if infoErr != nil {
continue
}
results = append(results, R{
"name": entry.Name(),
"isDir": info.IsDir(),
"isSymlink": util.IsSymlink(entry),
"updated": info.ModTime().Unix(),
})
}
result = resultsView on GitHub (pinned to 251596fc0d)
Solutions
- Create the directory first with siyuan.storage.mkdir before listing it.
- Catch the rejection and treat ENOENT (no such file or directory) as an empty list.
- Verify the path is a directory with siyuan.storage.stat before listing.
Example fix
// before
const entries = await siyuan.storage.list(dir);
// after
try {
return await siyuan.storage.list(dir);
} catch (e) {
if (/no such file or directory/.test(String(e?.cause ?? e))) return [];
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
let st; try { st = await siyuan.storage.stat(dir); } catch { st = null; } if (!st || !st.isDir) throw new Error('list target is not a directory'); Try / catch
try { return await siyuan.storage.list(dir); } catch (e) { const cause = String((e as any)?.cause ?? e); if (/no such file/.test(cause)) return []; throw e; } Prevention
- Ensure the directory exists (mkdir) before listing.
- Tolerate ENOENT as an empty result when listing optional dirs.
- stat() before list() when you need to branch on file-vs-dir.
When it happens
Trigger: await siyuan.storage.list(path) where path does not exist, is not a directory (it's a file), or the process lacks permission to open the directory.
Common situations: Listing before creating the directory, listing a path that was removed, or a permissions/ownership change on the storage dir.
Related errors
- failed to remove: %w
- save OAuth client registration: %w
- save OAuth credentials: %w
- failed to add storage path to watcher: %v
- failed to make directory: %w
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/bf7e1f0b6654bef1.
Report an issue: GitHub.