{"record":{"id":"0d8deb3fc9dbfb2f","repo":"siyuan-note/siyuan","slug":"failed-to-write-file-w","errorCode":null,"errorMessage":"failed to write file: %w","messagePattern":"failed to write file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/plugin/api_storage.go","lineNumber":282,"sourceCode":"\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.put 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.put 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 mkdirErr := os.MkdirAll(filepath.Dir(abs), 0755); mkdirErr != nil {\n\t\t\t\t\terr = fmt.Errorf(\"failed to make directory: %w\", mkdirErr)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif writeErr := filelock.WriteFile(abs, []byte(content)); writeErr != nil {\n\t\t\t\t\terr = fmt.Errorf(\"failed to write file: %w\", writeErr)\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.put 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.put 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.put reject: %v\", p.Name, rejectErr)\n\t\t\t}","sourceCodeStart":264,"sourceCodeEnd":300,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/plugin/api_storage.go#L264-L300","documentation":"filelock.WriteFile failed after the parent directories were successfully created while servicing siyuan.storage.put. The wrapped error (%w) is the underlying cause — typically disk full, permission denied on the target file, or the target path existing as a directory. The write is performed under SiYuan's file lock to avoid concurrent-write corruption.","triggerScenarios":"The workspace disk is full or quota-exhausted; the target file is read-only or owned by another user; the target path resolves to an existing directory; antivirus/backup tools hold the file during the locked write on Windows.","commonSituations":"Plugins writing large blobs that fill the workspace volume; files made read-only by sync clients (OneDrive/iCloud placeholders); a previously created directory occupying the exact target path.","solutions":["Inspect the wrapped OS error in the rejection for the concrete cause","Free disk space if the error indicates ENOSPC, and confirm workspace writability","Ensure the target path is not an existing directory; remove it or choose a different filename","Retry the put — transient locks from sync/AV tools often clear within seconds"],"exampleFix":"// before\nawait siyuan.storage.put(\"cache\", text); // \"cache\" is an existing directory\n// after\nawait siyuan.storage.put(\"cache/page.html\", text); // write into a file path instead","handlingStrategy":"retry","validationCode":"if (!path || path.endsWith(\"/\")) throw new TypeError(\"target must be a file path, not a directory\");","typeGuard":"const isFilePath = (p) => typeof p === \"string\" && p.length > 0 && !p.endsWith(\"/\");","tryCatchPattern":"try { await siyuan.storage.put(path, content); } catch (e) { if (String(e.message).includes(\"failed to write file\")) { await delay(500); return siyuan.storage.put(path, content); } throw e; }","preventionTips":["Retry transient write failures with a short backoff (sync clients and AV locks clear quickly)","Ensure the target path is not already a directory","Monitor free disk space for plugins storing large blobs","Prefer stable paths not touched by cloud-sync placeholders"],"tags":["plugins","filesystem","file-write","siyuan"],"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"}