Problem
When sending a book via email with "Embed metadata in sent files" enabled and a split library configuration, the send fails with:
ERROR {cps.tasks.mail:137} [Errno 2] No such file or directory: '/tmp/calibre_web/<uuid>.epub'
ERROR {cps.tasks.mail:269} The requested file could not be read. Maybe wrong permissions?
The user sees "Attachment not found" in the task list.
Root Cause
In _get_attachment() in cps/tasks/mail.py, when config_embed_metadata is enabled, do_calibre_export() is called to create a temporary EPUB with embedded metadata. If the export fails to produce a file (e.g. due to a transient NFS issue, a missing book file, or a calibredb export error), do_calibre_export() still returns a path via its fallback:
# Fallback to original behavior
return tmp_dir, temp_file_name
_get_attachment() then unconditionally overwrites datafile with this non-existent temp path:
data_path, data_file = do_calibre_export(self.book_id, extension)
datafile = os.path.join(data_path, data_file + "." + extension)
The original datafile (which pointed to the actual book file on disk and would have worked) is lost. The open() call fails and the send is aborted entirely.
Expected Behavior
If metadata embedding fails, the send should fall back to the original book file rather than failing completely. A book sent without re-embedded metadata is better than a book not sent at all.
Environment
- CWA latest (2026-03-28)
- Split library:
config_calibre_split = 1, metadata.db on local volume, book files on NFS
config_embed_metadata = 1
config_binariesdir = /usr/bin
Problem
When sending a book via email with "Embed metadata in sent files" enabled and a split library configuration, the send fails with:
The user sees "Attachment not found" in the task list.
Root Cause
In
_get_attachment()incps/tasks/mail.py, whenconfig_embed_metadatais enabled,do_calibre_export()is called to create a temporary EPUB with embedded metadata. If the export fails to produce a file (e.g. due to a transient NFS issue, a missing book file, or acalibredb exporterror),do_calibre_export()still returns a path via its fallback:_get_attachment()then unconditionally overwritesdatafilewith this non-existent temp path:The original
datafile(which pointed to the actual book file on disk and would have worked) is lost. Theopen()call fails and the send is aborted entirely.Expected Behavior
If metadata embedding fails, the send should fall back to the original book file rather than failing completely. A book sent without re-embedded metadata is better than a book not sent at all.
Environment
config_calibre_split = 1, metadata.db on local volume, book files on NFSconfig_embed_metadata = 1config_binariesdir = /usr/bin