{"record":{"id":"7998b10946f5bb1f","repo":"siyuan-note/siyuan","slug":"failed-to-remove-w","errorCode":null,"errorMessage":"failed to remove: %w","messagePattern":"failed to remove: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/plugin/api_storage.go","lineNumber":359,"sourceCode":"\t\t\t\t\t\terr = fmt.Errorf(\"panic during siyuan.storage.remove: %v\", r)\n\t\t\t\t\t}\n\n\t\t\t\t\tp.worker.Run(func(rt *goja.Runtime) (_ any, _ error) {\n\t\t\t\t\t\tif lo.IsNil(err) {\n\t\t\t\t\t\t\tif resolveErr := resolve(result); resolveErr != nil {\n\t\t\t\t\t\t\t\tlogging.LogErrorf(\"[plugin:%s] siyuan.storage.remove resolve: %v\", p.Name, resolveErr)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif rejectErr := reject(rt.NewGoError(err)); rejectErr != nil {\n\t\t\t\t\t\t\t\tlogging.LogErrorf(\"[plugin:%s] siyuan.storage.remove reject: %v\", p.Name, rejectErr)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn\n\t\t\t\t\t}, nil)\n\t\t\t\t}()\n\n\t\t\t\tif removeErr := os.RemoveAll(abs); removeErr != nil {\n\t\t\t\t\terr = fmt.Errorf(\"failed to remove: %w\", removeErr)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}()\n\n\t\t\treturn\n\t\t}, func(rt *goja.Runtime, result any, err error) {\n\t\t\tif !lo.IsNil(err) {\n\t\t\t\tif rejectErr := reject(rt.NewGoError(err)); rejectErr != nil {\n\t\t\t\t\tlogging.LogErrorf(\"[plugin:%s] siyuan.storage.remove reject: %v\", p.Name, rejectErr)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t\tif runErr != nil {\n\t\t\tlogging.LogErrorf(\"[plugin:%s] siyuan.storage.remove worker run: %v\", p.Name, runErr)\n\t\t\tif rejectErr := reject(rt.NewGoError(runErr)); rejectErr != nil {\n\t\t\t\tlogging.LogErrorf(\"[plugin:%s] siyuan.storage.remove reject: %v\", p.Name, rejectErr)\n\t\t\t}","sourceCodeStart":341,"sourceCodeEnd":377,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/plugin/api_storage.go#L341-L377","documentation":"Thrown by siyuan.storage.remove when os.RemoveAll fails to delete the resolved absolute path under the plugin's storage directory. The underlying OS error (permission denied, busy, not found) is wrapped with %w so it surfaces via the returned Promise rejection. It fires from a goroutine that recovers panics and routes errors to the JS reject handler.","triggerScenarios":"A plugin calls await siyuan.storage.remove(path) where path resolves under storageDir but the OS cannot delete it: file held open by another process, read-only filesystem, broken symlink, or the path was already removed concurrently.","commonSituations":"Running SiYuan with restrictive file permissions, antivirus/file-lock on Windows, a container with a read-only mounted storage volume, or a plugin that removes the same path from two concurrent calls.","solutions":["Check the wrapped error (err.cause) to see the real OS error before deciding what to do.","Ensure the SiYuan workspace/storage directory is writable by the kernel process and not locked by another app.","Avoid concurrent removes of the same path; await the first remove before retrying.","If the path may already be gone, catch the rejection and treat 'no such file or directory' as success."],"exampleFix":"// before\nawait siyuan.storage.remove(p);\n\n// after\ntry {\n  await siyuan.storage.remove(p);\n} catch (e) {\n  if (!/no such file or directory/.test(String(e?.cause ?? e))) throw e;\n}","handlingStrategy":"try-catch","validationCode":"if (typeof p !== 'string' || p.length === 0) throw new Error('remove: path required');","typeGuard":"function isRemovablePath(p: unknown): p is string { return typeof p === 'string' && p.length > 0 && !p.includes('..'); }","tryCatchPattern":"try { await siyuan.storage.remove(p); } catch (e) { const cause = String((e as any)?.cause ?? e); if (/no such file/.test(cause)) return; throw e; }","preventionTips":["Always pass a non-empty relative path that resolves under the plugin storage dir.","Await one remove before starting another on the same path.","Treat ENOENT in the wrapped cause as benign when the goal is ensure-gone."],"tags":["plugin","storage","filesystem","promise"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}