{"record":{"id":"5e1aabfd0914a418","repo":"siyuan-note/siyuan","slug":"conf-language-14-copy-assets-failed-s","errorCode":null,"errorMessage":"Conf.Language(14) (copy assets failed: %s)","messagePattern":"Conf\\.Language\\(14\\) \\(copy assets failed: (.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/export.go","lineNumber":1175,"sourceCode":"\t\toutput, pandocErr := pandoc.CombinedOutput()\n\t\tif pandocErr != nil {\n\t\t\targStr := strings.Join(args, \" \")\n\t\t\tmsg := gulu.DecodeCmdOutput(output)\n\t\t\tlogging.LogErrorf(\"export docx [%s] failed: %s\", argStr, msg)\n\t\t\treturn fmt.Errorf(Conf.Language(14), msg)\n\t\t}\n\n\t\tfullPath = filepath.Join(savePath, name+\".docx\")\n\t\tfullPath = util.GetUniqueFilename(fullPath)\n\t\tif copyErr := filelock.Copy(tmpDocxPath, fullPath); copyErr != nil {\n\t\t\tlogging.LogErrorf(\"export docx failed: %s\", copyErr)\n\t\t\treturn fmt.Errorf(Conf.Language(14), copyErr)\n\t\t}\n\n\t\tif tmpAssets := filepath.Join(tmpDir, \"assets\"); !removeAssets && gulu.File.IsDir(tmpAssets) {\n\t\t\tif copyErr := filelock.Copy(tmpAssets, filepath.Join(savePath, \"assets\")); copyErr != nil {\n\t\t\t\tlogging.LogErrorf(\"export docx failed: %s\", copyErr)\n\t\t\t\treturn fmt.Errorf(Conf.Language(14), copyErr)\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t})\n\tif err != nil {\n\t\tfullPath = \"\"\n\t}\n\treturn\n}\n\nfunc ExportMarkdownHTML(id, savePath string, docx, merge bool, mergeHeadingOptions ...MergeHeadingOptions) (name, dom string) {\n\tif err := prepareExportBlockAssets(id, merge); err != nil {\n\t\tutil.PushErrMsg(err.Error(), 7000)\n\t\treturn\n\t}\n\tname, dom, err := exportMarkdownHTML(id, savePath, docx, merge, mergeHeadingOptions...)\n\tif err != nil {\n\t\tlogging.LogErrorf(\"export markdown html [%s] failed: %s\", id, err)","sourceCodeStart":1157,"sourceCodeEnd":1193,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/export.go#L1157-L1193","documentation":"When removeAssets is false, ExportDocx copies the temporary assets/ directory next to the exported .docx so embedded images resolve. If filelock.Copy of the assets directory to <savePath>/assets fails, the localized 'Export failed: %s' template is filled with the error and returned.","triggerScenarios":"filelock.Copy(tmpAssets, filepath.Join(savePath, \"assets\")) fails: an existing assets directory or files inside it are locked/read-only, disk full, or permission denied on the destination.","commonSituations":"Destination already contains an assets folder with read-only files (e.g. from a previous export under version control or cloud sync); exporting onto a read-only volume; partial previous export left locked files.","solutions":["Ensure no process locks files under <savePath>/assets (close editors, pause cloud sync) and retry.","Export to a fresh directory instead of one containing a previous assets folder.","Make existing destination asset files writable or remove the stale assets directory manually.","Check free disk space and directory write permissions for the save path."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// preflight: check existing assets dir is writable\nconst assetsDir = savePath + \"/assets\";\nif (await dirExists(assetsDir)) await ensureWritable(assetsDir);","typeGuard":null,"tryCatchPattern":"try {\n  await exportDocx({id, savePath});\n} catch (e) {\n  if (String(e.msg).includes('assets')) {\n    adviseClearingStaleAssetsDir();\n  }\n}","preventionTips":["Export to clean directories when possible","Pause cloud-sync clients that may lock files in the destination assets folder","Remove read-only flags from previously exported asset files"],"tags":["file-copy","assets","export","docx","filesystem"],"backgroundTag":"file-write-failed","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}