siyuan-note/siyuan · error

path and content required

Error message

path and content required

What it means

Thrown by siyuan.storage.put() when fewer than two arguments are supplied. put writes content to a file under the plugin storage dir and requires both a path and a content string. The check is purely on argument count (len < 2), so omitting either the path or the content triggers it; note it does not additionally verify the types.

Source

Thrown at kernel/plugin/api_storage.go:235

		})
		if runErr != nil {
			logging.LogErrorf("[plugin:%s] siyuan.storage.get worker run: %v", p.Name, runErr)
			if rejectErr := reject(rt.NewGoError(runErr)); rejectErr != nil {
				logging.LogErrorf("[plugin:%s] siyuan.storage.get reject: %v", p.Name, rejectErr)
			}
		}

		return rt.ToValue(promise)
	})))

	// siyuan.storage.put(path, content) -> Promise<void>
	lo.Must0(storage.Set("put", rt.ToValue(func(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
		promise, resolve, reject := rt.NewPromise()

		var argErr error
		var path, content string
		if len(call.Arguments) < 2 {
			argErr = fmt.Errorf("path and content required")
		} else {
			path = call.Argument(0).String()
			content = call.Argument(1).String()
		}

		runErr := p.worker.Run(func(rt *goja.Runtime) (result any, err error) {
			if argErr != nil {
				err = argErr
				return
			}
			if util.ReadOnly {
				err = fmt.Errorf("The current kernel is in read-only mode, storage.put is not allowed")
				return
			}

			abs, resolveErr := resolvePath(path)
			if resolveErr != nil {
				err = resolveErr

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Always pass both arguments: put(path, content).
  2. Default content to an empty string when you intentionally want to truncate.
  3. Validate that the content variable is defined before calling put.

Example fix

// before
await siyuan.storage.put('state.json');
// after
await siyuan.storage.put('state.json', JSON.stringify(state));
Defensive patterns

Strategy: validation

Validate before calling

if (arguments.length < 2 || typeof path !== 'string') {
  throw new TypeError('storage.put requires (path: string, content: string)');
}

Type guard

const isPutArgs = (p, c) => typeof p === 'string' && typeof c === 'string';

Try / catch

try { await siyuan.storage.put(path, content); }
catch (e) { if (/path and content required/.test(String(e))) { /* missing arg */ } else throw e; }

Prevention

When it happens

Trigger: Calling storage.put('x') with only a path and no content; put() with no arguments; put(undefined, undefined).

Common situations: Plugin builds the content lazily and forgets to pass it when empty; serialization step that produced undefined content was skipped; refactor changed put signatures and a call site was missed.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/50cb2f634888ba19. Report an issue: GitHub.