siyuan-note/siyuan · error
failed to add storage path to watcher: %v
Error message
failed to add storage path to watcher: %v
What it means
Thrown when p.addStorageWatch(abs) returns an error after the path was successfully resolved. The kernel registers the absolute storage path with its underlying file watcher (fsnotify-based); if registration fails the promise rejects with the wrapped underlying error in place of %v. Common underlying causes: the path does not exist yet, permission denied, OS watcher/inotify limits exceeded, or the path is a file whose parent cannot be watched.
Source
Thrown at kernel/plugin/api_storage.go:73
var path string
if len(call.Arguments) >= 1 && goja.IsString(call.Argument(0)) {
path = call.Argument(0).String()
} else {
argErr = fmt.Errorf("path required")
}
runErr := p.worker.Run(func(rt *goja.Runtime) (result any, err error) {
if argErr != nil {
err = argErr
return
}
abs, resolveErr := resolvePath(path)
if resolveErr != nil {
err = resolveErr
return
}
if addErr := p.addStorageWatch(abs); addErr != nil {
err = fmt.Errorf("failed to add storage path to watcher: %v", addErr)
}
return
}, func(rt *goja.Runtime, result any, err error) {
if lo.IsNil(err) {
if resolveErr := resolve(result); resolveErr != nil {
logging.LogErrorf("[plugin:%s] siyuan.storage.watcher.add resolve: %v", p.Name, resolveErr)
}
} else {
if rejectErr := reject(rt.NewGoError(err)); rejectErr != nil {
logging.LogErrorf("[plugin:%s] siyuan.storage.watcher.add reject: %v", p.Name, rejectErr)
}
}
})
if runErr != nil {
logging.LogErrorf("[plugin:%s] siyuan.storage.watcher.add worker run: %v", p.Name, runErr)
if rejectErr := reject(rt.NewGoError(runErr)); rejectErr != nil {
logging.LogErrorf("[plugin:%s] siyuan.storage.watcher.add reject: %v", p.Name, rejectErr)
}View on GitHub (pinned to 251596fc0d)
Solutions
- Ensure the file or directory exists (create it via storage.put) before calling watcher.add.
- Raise the OS watcher limit (e.g. echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf on Linux).
- Check file permissions on the storage dir and its parents.
- Watch the parent directory instead of a non-existent leaf when appropriate.
Example fix
// before
await siyuan.storage.watcher.add('cache/state.json');
// after
await siyuan.storage.put('cache/state.json', '{}');
await siyuan.storage.watcher.add('cache/state.json'); Defensive patterns
Strategy: try-catch
Validate before calling
// Ensure target exists before watching:
try { await siyuan.storage.get(path); } catch { await siyuan.storage.put(path, ''); } Try / catch
try {
await siyuan.storage.watcher.add(path);
} catch (e) {
console.warn('watcher.add failed:', String(e));
// optionally retry once after ensuring the file exists
} Prevention
- Create the file or directory with storage.put before watching it.
- On Linux, raise fs.inotify.max_user_watches for plugins that watch many paths.
- Confirm the storage dir is on a local filesystem fsnotify supports.
When it happens
Trigger: watcher.add('subdir/file.json') where 'subdir/file.json' does not exist on disk; on Linux hitting fs.inotify.max_user_watches; on Windows a path held open exclusively by another process; watching a network mount the watcher cannot monitor.
Common situations: Plugin tries to watch a path before creating it (call put first, then add); deployment on a restricted container with low inotify limits; symlinked storage dir on a filesystem fsnotify does not support.
Related errors
- failed to remove storage path from watcher: %v
- path required
- The current kernel is in read-only mode, storage.put is not
- failed to make directory: %w
- failed to write file: %w
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/73e1ae11e367436c.
Report an issue: GitHub.