siyuan-note/siyuan · error
Conf.Language(14) (copy resource failed: %s)
Error message
Conf.Language(14) (copy resource failed: %s)
What it means
When copying a resource file/folder into the temporary export directory fails, ExportResources wraps the underlying OS error with the localized template Conf.Language(14) ('copy resource failed: %s'). The original error (permissions, missing file, disk full, name collision) is embedded via fmt.Errorf so the log records the source and destination while the user sees a friendly message.
Source
Thrown at kernel/model/export.go:886
os.Remove(zipFilePath)
os.Remove(zipFilePath + ".partial")
}
}()
// 将需要导出的文件/文件夹复制到临时文件夹
for _, resourcePath := range resourcePaths {
resourceFullPath := filepath.Join(util.WorkspaceDir, resourcePath) // 资源完整路径
if !util.IsAbsPathInWorkspace(resourceFullPath) {
logging.LogErrorf("resource path [%s] is not in workspace", resourceFullPath)
err = errors.New("resource path [" + resourcePath + "] is not in workspace")
return
}
resourceBaseName := filepath.Base(resourceFullPath) // 资源名称
resourceCopyPath := filepath.Join(exportFolderPath, resourceBaseName) // 资源副本完整路径
if err = copyExportResource(resourceFullPath, resourceCopyPath); err != nil {
logging.LogErrorf("copy resource will be exported from [%s] to [%s] failed: %s", resourcePath, resourceCopyPath, err)
err = fmt.Errorf(Conf.Language(14), err.Error())
return
}
}
zipPartialPath := zipFilePath + ".partial"
zip, err := gulu.Zip.Create(zipPartialPath)
if err != nil {
logging.LogErrorf("create export zip [%s] failed: %s", zipFilePath, err)
return
}
zipClosed := false
defer func() {
if !zipClosed {
_ = zip.Close()
}
}()
if err = zip.AddDirectory(zipBaseName, exportFolderPath); err != nil {View on GitHub (pinned to 8641553a1f)
Solutions
- Read the wrapped %s detail to find the underlying cause (missing file, permission, disk space)
- Verify the source resource still exists and is readable before exporting
- Free disk space / check write permissions on the temp export directory
- Retry after resolving file locks (close apps holding the file, exclude from AV scanning)
Example fix
// before // source may have been deleted await exportResources(staleAssetPaths); // after const existing = staleAssetPaths.filter(p => fs.existsSync(path.join(workspaceDir, p))); await exportResources(existing);
Defensive patterns
Strategy: try-catch
Validate before calling
for _, p := range paths {
if _, err := os.Stat(filepath.Join(util.WorkspaceDir, p)); err != nil {
return fmt.Errorf("resource missing before export: %s", p)
}
} Try / catch
_, err := model.ExportResources(paths, name)
if err != nil {
var msg string
fmt.Sscanf(err.Error(), Conf.Language(14), &msg) // unwrap %s detail
log.Printf("export copy failed: %s", msg)
} Prevention
- Verify each source path exists right before exporting
- Check free disk space in the temp directory
- Handle Windows file locks (AV, search indexer) on asset folders
When it happens
Trigger: copyExportResource returns an error for any resource in the list — source deleted between listing and copy, read permission denied, destination write failure in TempDir/export, directory walk error, or disk quota exhausted.
Common situations: Asset file removed or renamed after the export list was built; read-only or AV-scanner-locked files on Windows; temp directory on a full disk; exporting a directory containing files the process cannot read.
Related errors
- Conf.Language(14) (copy docx failed: %s)
- Conf.Language(14) (copy assets failed: %s)
- Export failed: %s
- read session file failed: %w
- create session dir failed: %w
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/2aa62b7fa5f77db2.
Report an issue: GitHub.