siyuan-note/siyuan · error

failed to remove

Error message

failed to remove: %w

What it means

os.RemoveAll failed while deleting the resolved path for siyuan.storage.remove. The underlying OS error (permissions, file in use, nonexistent path on some platforms, etc.) is wrapped with %w and the Promise is rejected with 'failed to remove: <cause>'.

Solutions

  1. Read the wrapped cause to identify the OS error (EACCES/EBUSY/ENOENT)
  2. Ensure the calling plugin has the necessary storage permissions and the target is not open elsewhere
  3. Retry after a short delay if a lock/AV scanner held the file
  4. Close file handles the plugin itself holds before removing

Example fix

// before
await siyuan.storage.remove(file);

// after
try {
  await siyuan.storage.remove(file);
} catch (e) {
  console.error("remove failed:", String(e)); // inspect wrapped OS cause
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await siyuan.storage.remove(path);
} catch (e) {
  const cause = String(e); // 'failed to remove: <os error>'
  if (cause.includes("permission denied") || cause.includes("resource temporarily unavailable")) {
    // retry after delay or notify user
  } else throw e;
}

Prevention

When it happens

Trigger: Calling siyuan.storage.remove(path) where the OS cannot delete the target: insufficient permissions, the file/directory is locked by another process, or a nested entry cannot be removed so RemoveAll aborts.

Common situations: Files opened by another application on Windows; read-only file attributes; permission changes on the storage directory; antivirus holding files briefly.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


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

Appendix: source

Thrown at kernel/plugin/api_storage.go:359

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

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

View on GitHub (pinned to 9f775e8a12)