siyuan-note/siyuan · error

cannot remove storage root

Error message

cannot remove storage root

What it means

siyuan.storage.remove resolves the given path inside the plugin's storage directory and refuses to delete the storage root itself (abs == p.storageDir). Deleting the root would wipe all plugin storage, so the API rejects with 'cannot remove storage root'.

Solutions

  1. Pass a path that points to a specific file or subdirectory, not the root
  2. Guard the call: skip removal when the path is empty or resolves to the root
  3. To clear all data, iterate siyuan.storage.list('/') and remove each entry individually instead of removing the root

Example fix

// before
await siyuan.storage.remove(path || "/");

// after
if (path && path !== "/") {
  await siyuan.storage.remove(path);
}
Defensive patterns

Strategy: validation

Validate before calling

function canRemove(p) {
  const norm = "/" + String(p ?? "").replace(/^\/+/, "");
  return norm !== "/" && norm.length > 1;
}
if (!canRemove(path)) throw new Error("refusing to remove storage root");

Try / catch

try {
  await siyuan.storage.remove(path);
} catch (e) {
  if (String(e).includes("storage root")) {
    console.warn("path resolved to storage root; skipped");
  } else throw e;
}

Prevention

When it happens

Trigger: Calling siyuan.storage.remove("") or siyuan.storage.remove("/") or any path that resolves exactly to the plugin storage directory root. Path resolution normalizes the input, so any spelling that lands on the root triggers this.

Common situations: Plugin cleanup code that computes a path from an empty variable or default; calling remove with no meaningful segment; a loop that deletes all entries and also targets the root.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/39bcc3722f398739. Report an issue: GitHub.

Appendix: source

Thrown at kernel/plugin/api_storage.go:334

		}

		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.remove is not allowed")
				return
			}

			abs, resolveErr := resolvePath(path)
			if resolveErr != nil {
				err = resolveErr
				return
			}
			if abs == p.storageDir {
				err = fmt.Errorf("cannot remove storage root")
				return
			}

			go func() (result any, err error) {
				defer func() {
					if r := recover(); r != nil {
						err = fmt.Errorf("panic during siyuan.storage.remove: %v", r)
					}

					p.worker.Run(func(rt *goja.Runtime) (_ any, _ error) {
						if lo.IsNil(err) {
							if resolveErr := resolve(result); resolveErr != nil {
								logging.LogErrorf("[plugin:%s] siyuan.storage.remove resolve: %v", p.Name, resolveErr)
							}
						} else {
							if rejectErr := reject(rt.NewGoError(err)); rejectErr != nil {
								logging.LogErrorf("[plugin:%s] siyuan.storage.remove reject: %v", p.Name, rejectErr)
							}

View on GitHub (pinned to 9f775e8a12)