siyuan-note/siyuan · error
initialize fsnotify watcher: %w
Error message
initialize fsnotify watcher: %w
What it means
Returned by addStorageWatch when fsnotify.NewWatcher() fails while lazily initializing the file watcher on first watch. The OS-level inotify/kqueue/ReadDirectoryChangesW error is wrapped. Once it fails p.watcher stays nil so a later Add is not attempted on a bad watcher.
Source
Thrown at kernel/plugin/plugin.go:780
}
}
// addStorageWatch adds a path to the fsnotify watcher to watch for storage file/directory changes.
func (p *KernelPlugin) addStorageWatch(path string) (err error) {
if !isPluginFileWatchSupported() {
return errPluginFileWatchUnsupported
}
p.watcherMu.Lock()
defer p.watcherMu.Unlock()
if contextErr := p.context.Err(); contextErr != nil {
return fmt.Errorf("plugin stopped: %w", contextErr)
}
if p.watcher == nil {
p.watcher, err = fsnotify.NewWatcher()
if err != nil {
return fmt.Errorf("initialize fsnotify watcher: %w", err)
}
p.watcherDone = make(chan struct{})
go p.startStorageWatch(p.watcher, p.watcherDone)
}
err = p.watcher.Add(path)
return
}
// removeStorageWatch removes a path from the fsnotify watcher to stop watching for storage file/directory changes.
func (p *KernelPlugin) removeStorageWatch(path string) (err error) {
if !isPluginFileWatchSupported() {
return errPluginFileWatchUnsupported
}
p.watcherMu.Lock()
defer p.watcherMu.Unlock()
View on GitHub (pinned to 251596fc0d)
Solutions
- On Linux raise fs.inotify.max_user_watches (sysctl) and fs.file-max, then retry the watch.
- Reduce the number/depth of watched directories; watch specific files instead of trees.
- Run SiYuan on a platform with fsnotify support; on mobile this path returns errPluginFileWatchUnsupported instead.
- Check the kernel log for the matching ENOMEM/ENOSPC from inotify_add_watch.
Example fix
# before (host default inotify limit) # plugin call fails with 'initialize fsnotify watcher: ...' # after (raise inotify watch limit) sudo sysctl fs.inotify.max_user_watches=524288 sudo sysctl fs.inotify.max_user_instances=512
Defensive patterns
Strategy: try-catch
Validate before calling
// host-level: ensure fs.inotify.max_user_watches is high enough // (no runtime guard from plugin JS; check platform limits before adding watches)
Try / catch
try { await siyuan.storage.watcher.add(path); } catch (e) { if (/fsnotify|inotify/i.test(String(e))) { console.warn('watch unsupported, polling fallback', e); /* fall back to polling */ } else throw e; } Prevention
- Raise fs.inotify.max_user_watches on Linux hosts.
- Watch specific files/subdirs, not entire trees.
- Fall back to periodic polling when fsnotify add fails.
When it happens
Trigger: Calling siyuan.storage.watcher.add(path) for the first time on a system that is out of inotify watches/watches, has too many open file descriptors, or lacks kernel inotify support.
Common situations: Linux hosts with fs.inotify.max_user_watches set too low for many plugins/files, containers with a restricted procfs, or embedded/mobile builds where fsnotify is unavailable.
Related errors
- fsnotify watcher not initialized
- failed to add storage path to watcher: %v
- failed to remove storage path from watcher: %v
- Agent capability name and description are required
- ${data.error.message}
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/bdb2a30406d18f91.
Report an issue: GitHub.