{"record":{"id":"9f2f16c3c706b792","repo":"siyuan-note/siyuan","slug":"remove-unused-asset-s-failed-w","errorCode":null,"errorMessage":"remove unused asset [%s] failed: %w","messagePattern":"remove unused asset \\[(.+?)\\] failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/assets.go","lineNumber":1631,"sourceCode":"\n\thistoryPath := filepath.Join(historyDir, filepath.FromSlash(relativePath))\n\tif err = filelock.Copy(absPath, historyPath); err != nil {\n\t\terr = fmt.Errorf(\"copy unused asset [%s] to history failed: %w\", absPath, err)\n\t\treturn\n\t}\n\n\thash, _ := util.GetEtag(absPath)\n\tsql.BatchRemoveAssetsQueue([]string{hash})\n\tcache.RemoveAssetHash(hash)\n\n\tif util.IsMobileContainer() {\n\t\tHandleAssetsRemoveEvent(absPath)\n\t}\n\n\tif err = filelock.RemoveWithoutFatal(absPath); err != nil {\n\t\tlogging.LogErrorf(\"remove unused asset [%s] failed: %s\", absPath, err)\n\t\tutil.PushErrMsg(fmt.Sprintf(\"%s\", err), 7000)\n\t\terr = fmt.Errorf(\"remove unused asset [%s] failed: %w\", absPath, err)\n\t\treturn\n\t}\n\tret = absPath\n\n\tutil.RemoveAssetText(relativePath)\n\n\tIncSync()\n\n\tindexHistoryDir(filepath.Base(historyDir), util.NewLute())\n\tcache.RemoveAsset(relativePath)\n\treturn\n}\n\nfunc RenameAsset(oldPath, newName string) (newPath string, err error) {\n\tutil.PushEndlessProgress(Conf.Language(110))\n\tdefer util.PushClearProgress()\n\n\toldCleanPath := AssetPathWithoutQuery(oldPath)","sourceCodeStart":1613,"sourceCodeEnd":1649,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/assets.go#L1613-L1649","documentation":"The kernel failed to delete an unused asset file from disk during asset cleanup. SiYuan removes assets that are no longer referenced by any document; when the underlying file removal (filelock.RemoveWithoutFatal) fails, the absolute path and OS error are wrapped and pushed to the UI as an error message. The original error is preserved via %w wrapping.","triggerScenarios":"RemoveUnusedAsset / HandleAssetsRemoveEvent flow deletes an asset file and the OS remove fails — typically because the file is locked by another process (open in an external editor, AV scanner, sync client), the file was already deleted, or the user lacks write permission on the file or its parent directory.","commonSituations":"Cloud-sync clients (OneDrive/Dropbox) holding file locks on Windows; antivirus scanning the file mid-delete; read-only data directory; the asset deleted concurrently by another SiYuan instance or sync; filesystem errors on removable/network drives.","solutions":["Check no other process (editor, sync client, antivirus) is holding the asset file open, then retry the removal","Verify the data directory and workspace/assets folder are writable by the SiYuan process user","Confirm the asset file still exists; if it was already removed by sync or another instance, refresh the asset panel","Check disk health/free space and OS-level error details in the kernel log (logging.LogErrorf output)","Restart SiYuan to release internal handles and retry the cleanup"],"exampleFix":"// before: removal fails silently blocking cleanup\nif err = filelock.RemoveWithoutFatal(absPath); err != nil { ... }\n// after (user-side): close the app holding the asset, ensure file is unlocked, then retry\ncloseExternalEditors(assetPath); retryAssetRemoval()","handlingStrategy":"try-catch","validationCode":"// before triggering cleanup, check writability\nimport fs from 'fs';\nif (!fs.accessSync(assetAbsPath, fs.constants.W_OK)) throw new Error('asset not writable');","typeGuard":null,"tryCatchPattern":"try { await removeUnusedAsset(path) } catch (e) {\n  if (e.message.includes('remove unused asset')) {\n    // file likely locked/permission issue; notify user to close editors/sync clients\n    showLockHint(path);\n  }\n}","preventionTips":["Keep the workspace out of folders managed by aggressive sync/AV tools","Close external editors holding asset files before bulk cleanup","Run SiYuan with write permissions on the whole workspace"],"tags":["filesystem","file-delete","assets"],"backgroundTag":"file-write-failed","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}