siyuan-note/siyuan · error
initialize fsnotify watcher
Error message
initialize fsnotify watcher: %w
What it means
addStorageWatch lazily creates the plugin's fsnotify watcher. If fsnotify.NewWatcher() fails (e.g. the platform lacks inotify support or the OS exhausted watch resources), the error is wrapped as 'initialize fsnotify watcher: <cause>'.
Solutions
- Raise fs.inotify.max_user_instances and fs.inotify.max_user_watches (sysctl) on Linux
- Reduce the number of watched paths (watch fewer directories, use recursive logic sparingly)
- On mobile/unsupported platforms, avoid file-watch APIs and use polling or explicit refresh instead
- Check the wrapped cause to confirm resource exhaustion vs platform limitation
Example fix
// before
await plugin.addStorageWatch(largeDir);
// after
try {
await plugin.addStorageWatch(largeDir);
} catch (e) {
console.warn("watch unavailable, falling back to polling:", String(e));
}
Defensive patterns
Strategy: fallback
Try / catch
try {
await plugin.addStorageWatch(path);
} catch (e) {
if (String(e).includes("initialize fsnotify watcher")) {
startPollingFallback(path); // poll mtime instead of fsnotify
} else throw e;
} Prevention
- On Linux, keep fs.inotify.max_user_instances/watches high enough
- Limit the number of concurrently watched paths
- On mobile/unsupported platforms use polling instead of file watches
When it happens
Trigger: First storage-watch registration on a plugin when no watcher exists yet and the OS cannot create one: inotify instances/watch descriptors exhausted (Linux), unsupported platform (mobile builds disable file watching), or resource limits.
Common situations: Linux systems with low fs.inotify.max_user_instances/max_user_watches; containers with restricted inotify; mobile kernels where watching is disabled; watching very large directory trees exhausting descriptors.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- fsnotify watcher not initialized
- plugin stopped
- failed to add storage path to watcher
- failed to remove storage path from watcher
- writing file paths to clipboard is not supported on this…
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/bdb2a30406d18f91.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/plugin/plugin.go:781
}
}
// 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 9f775e8a12)