siyuan-note/siyuan · error
path required
Error message
path required
What it means
Thrown by siyuan.storage.watcher.add() when no string path argument is supplied. watcher.add registers a path under the plugin storage dir with the kernel file watcher so the plugin receives change notifications. It requires at least one argument that is a string; missing or non-string arguments are rejected up front.
Source
Thrown at kernel/plugin/api_storage.go:59
abs = filepath.Join(p.storageDir, filepath.Clean(relPath))
if !(abs == p.storageDir || strings.HasPrefix(abs, p.storageDir+string(filepath.Separator))) {
err = fmt.Errorf("siyuan.storage: path traversal not allowed")
}
return
}
watcher := rt.NewObject()
// siyuan.storage.watcher.add(path) -> Promise<void>
lo.Must0(watcher.Set("add", rt.ToValue(func(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
promise, resolve, reject := rt.NewPromise()
var argErr error
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) {View on GitHub (pinned to 251596fc0d)
Solutions
- Pass a non-empty relative path string that lives under the storage dir.
- Default optional path variables to a sensible relative string before calling add.
- Skip the add call when the resolved path is empty or not a string.
Example fix
// before
await siyuan.storage.watcher.add(maybePath);
// after
if (typeof maybePath === 'string' && maybePath) {
await siyuan.storage.watcher.add(maybePath);
} Defensive patterns
Strategy: validation
Validate before calling
if (typeof path !== 'string' || path.length === 0) {
throw new TypeError('watcher.add requires a non-empty path string');
} Type guard
const isStoragePath = (p) => typeof p === 'string' && p.length > 0;
Try / catch
try { await siyuan.storage.watcher.add(path); }
catch (e) { if (/path required/.test(String(e))) { /* skip watch */ } else throw e; } Prevention
- Default optional path variables to a concrete relative string.
- Skip add when the resolved path is empty or not a string.
When it happens
Trigger: Calling watcher.add() with no arguments, watcher.add(undefined), or watcher.add(123). The check is len(call.Arguments) >= 1 && goja.IsString(call.Argument(0)).
Common situations: Plugin derives the watch path from a variable that is sometimes undefined (e.g. a config field not yet loaded), or calls add in a loop where one entry is empty.
Related errors
- path and content required
- method name required
- method required
- failed to add storage path to watcher: %v
- failed to remove storage path from watcher: %v
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/222df829404f838b.
Report an issue: GitHub.