V14 error sending emails with 'Attach Document Print'

In v14, we’ve started seeing email messages getting stuck in the Email Queue. When you send an email from a document and use the ‘Attach Document Print’ option, the message sits in the queue as ‘Not Sent’ for several minutes until eventually, it goes into error state and the below message appears in the Error Log. I’ve confirmed that it occurs for multiple doctypes and both stock and custom print formats.

I found this thread where a somewhat similar issue was reported. My environment is containerized, as well. Per the resolution on that thread, I’ve checked that the assets directory is mounted. I can exec into the gunicorn container. There are files in the assets/ dir and it’s writeable to the exec user. I’m not sure if there’s anything else there to check?

Edit: One other quirk worth mentioning: If I go into the message in the queue and hit ‘send now’, it sends successfully without complaint.

Edit #2: While my assets directory is populated in the gunicorn container, it’s empty in the worker container so this may be the problem, after all.

Edit #3: Empty assets directory in worker containers seems to be normal. Back to the drawing board.

Frappe: v14.8.0
ERPNext: 14.1.2

Thanks in advance for any help!

—CUT—
File “/home/frappe/frappe-bench/apps/frappe/frappe/email/doctype/email_queue/email_queue.py”, line 134, in send
message = ctx.build_message(recipient.recipient)
File “/home/frappe/frappe-bench/apps/frappe/frappe/email/doctype/email_queue/email_queue.py”, line 293, in build_message
message = self.include_attachments(message)
File “/home/frappe/frappe-bench/apps/frappe/frappe/email/doctype/email_queue/email_queue.py”, line 356, in include_attachments
print_format_file = frappe.attach_print(**attachment)
File “/home/frappe/frappe-bench/apps/frappe/frappe/init.py”, line 2076, in attach_print
content = get_print(doctype, name, **kwargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/init.py”, line 2026, in get_print
html = get_response_content(“printview”)
File “/home/frappe/frappe-bench/apps/frappe/frappe/website/serve.py”, line 33, in get_response_content
response = get_response(path, http_status_code)
File “/home/frappe/frappe-bench/apps/frappe/frappe/website/serve.py”, line 27, in get_response
response = ErrorPage(exception=e).render()
File “/home/frappe/frappe-bench/apps/frappe/frappe/website/page_renderers/template_page.py”, line 78, in render
html = self.get_html()
File “/home/frappe/frappe-bench/apps/frappe/frappe/website/utils.py”, line 510, in cache_html_decorator
html = func(*args, **kwargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/website/page_renderers/template_page.py”, line 95, in get_html
html = self.render_template()
File “/home/frappe/frappe-bench/apps/frappe/frappe/website/page_renderers/template_page.py”, line 232, in render_template
html = frappe.render_template(self.source, self.context, safe_render=safe_render)
File “/home/frappe/frappe-bench/apps/frappe/frappe/utils/jinja.py”, line 85, in render_template
return get_jenv().from_string(template).render(context)
File “/home/frappe/frappe-bench/env/lib/python3.10/site-packages/jinja2/environment.py”, line 1301, in render
self.environment.handle_exception()
File “/home/frappe/frappe-bench/env/lib/python3.10/site-packages/jinja2/environment.py”, line 936, in handle_exception
raise rewrite_traceback_stack(source=source)
File “”, line 1, in top-level template code
File “/home/frappe/frappe-bench/apps/frappe/frappe/templates/web.html”, line 1, in top-level template code
{% extends base_template_path %}
File “/home/frappe/frappe-bench/apps/frappe/frappe/templates/base.html”, line 25, in top-level template code
{%- block head -%}
File “/home/frappe/frappe-bench/apps/frappe/frappe/templates/base.html”, line 33, in block ‘head’
{{ include_style(‘website.bundle.css’) }}
File “/home/frappe/frappe-bench/env/lib/python3.10/site-packages/jinja2/sandbox.py”, line 393, in call
return __context.call(__obj, *args, **kwargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/utils/jinja_globals.py”, line 118, in include_style
path = bundled_asset(path)
File “/home/frappe/frappe-bench/apps/frappe/frappe/utils/jinja_globals.py”, line 136, in bundled_asset
path = bundled_assets.get(path) or path

The most specific error I can find:

20:32:49 home-frappe-frappe-bench:short: Job OK (7cdd9955-71fb-4432-9bcd-2672ff4d70b0)
20:32:49 Result is kept for 600 seconds
20:32:49 home-frappe-frappe-bench:short: frappe.utils.background_jobs.execute_job(event=‘all’, is_async=True, job_name=‘pull_from_email_account|Notifications’, kwargs={‘email_account’: ‘Notifications’}, method=<function pull_from_email_account at 0x7f4dea45d360>, site=‘xxx.xxxxx.xxx’, user=‘Administrator’) (cacdb308-ec6a-4010-bb1b-feb75733c199)
/home/frappe/frappe-bench/apps/frappe/frappe/database/query.py:197: UserWarning: The ‘filters_config’ hook used to add custom operators is not yet implemented in frappe.db.query engine. Use db_query (frappe.get_list) instead.
warn(
20:32:50 home-frappe-frappe-bench:short: Job OK (cacdb308-ec6a-4010-bb1b-feb75733c199)
20:32:50 Result is kept for 600 seconds
20:32:50 home-frappe-frappe-bench:short: frappe.utils.background_jobs.execute_job(event=None, is_async=True, job_name=’<function send_mail at 0x7f4dea020d30>’, kwargs={‘email_queue_name’: ‘15ecb36ca0’, ‘is_background_task’: True}, method=<function send_mail at 0x7f4dea020d30>, site=‘xxx.xxxxxx.xxx’, user=‘Administrator’) (e35bd878-8762-4171-86fa-31bd3bde2a49)
/home/frappe/frappe-bench/apps/frappe/frappe/database/query.py:197: UserWarning: The ‘filters_config’ hook used to add custom operators is not yet implemented in frappe.db.query engine. Use db_query (frappe.get_list) instead.
warn(
20:32:52 Traceback (most recent call last):
File “/home/frappe/frappe-bench/apps/frappe/frappe/website/serve.py”, line 18, in get_response
response = renderer_instance.render()
File “/home/frappe/frappe-bench/apps/frappe/frappe/website/page_renderers/template_page.py”, line 78, in render
html = self.get_html()
File “/home/frappe/frappe-bench/apps/frappe/frappe/website/utils.py”, line 510, in cache_html_decorator
html = func(*args, **kwargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/website/page_renderers/template_page.py”, line 95, in get_html
html = self.render_template()
File “/home/frappe/frappe-bench/apps/frappe/frappe/website/page_renderers/template_page.py”, line 232, in render_template
html = frappe.render_template(self.source, self.context, safe_render=safe_render)
File “/home/frappe/frappe-bench/apps/frappe/frappe/utils/jinja.py”, line 85, in render_template
return get_jenv().from_string(template).render(context)
File “/home/frappe/frappe-bench/env/lib/python3.10/site-packages/jinja2/environment.py”, line 1301, in render
self.environment.handle_exception()
File “/home/frappe/frappe-bench/env/lib/python3.10/site-packages/jinja2/environment.py”, line 936, in handle_exception
raise rewrite_traceback_stack(source=source)
File “”, line 8, in top-level template code
File “/home/frappe/frappe-bench/env/lib/python3.10/site-packages/jinja2/sandbox.py”, line 393, in call
return __context.call(__obj, *args, **kwargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/utils/jinja_globals.py”, line 118, in include_style
path = bundled_asset(path)
File “/home/frappe/frappe-bench/apps/frappe/frappe/utils/jinja_globals.py”, line 136, in bundled_asset
path = bundled_assets.get(path) or path
AttributeError: ‘NoneType’ object has no attribute ‘get’