siyuan-note/siyuan · error

panic during siyuan.storage.remove: %v

Error message

panic during siyuan.storage.remove: %v

What it means

Thrown when a panic is recovered inside the goroutine that performs the deletion for siyuan.storage.remove(). The deferred recover() wraps the panic value into this message. It is a defensive boundary for unexpected runtime faults during the remove operation, separate from ordinary OS errors which propagate through the worker error path.

Source

Thrown at kernel/plugin/api_storage.go:341

			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)
							}
						}
						return
					}, nil)
				}()

				if removeErr := os.RemoveAll(abs); removeErr != nil {
					err = fmt.Errorf("failed to remove: %w", removeErr)

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Inspect the %v detail in the kernel log to locate the panic site.
  2. Avoid issuing remove calls during plugin unload; serialize shutdown ordering.
  3. Retry once to rule out a transient teardown race.
  4. Wrap remove in try/catch and continue if the file is already gone.

Example fix

// before
await siyuan.storage.remove(path);
// after
try {
  await siyuan.storage.remove(path);
} catch (e) {
  console.warn('storage.remove failed, assuming already removed', e);
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await siyuan.storage.remove(path);
} catch (e) {
  if (/panic during siyuan.storage.remove/.test(String(e))) {
    console.warn('remove panicked, treating as removed', path);
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: A panic inside the remove goroutine — e.g. nil dereference in filelock or os.Remove helpers, or a runtime fault during concurrent plugin teardown.

Common situations: Very rare; usually points to a kernel defect or a race during shutdown when the storage watcher is being torn down while a remove is in flight.

Related errors


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