本文目前仅提供英文版本。翻译即将推出。
A user prints an Odoo report. The PDF downloads. The PDF is one blank page (sometimes more). The HTML preview in the browser looks fine — content visible, formatting correct. Only the PDF is empty. The server log shows a clean run:
INFO: Generated report sale.report_saleorder for record sale.order(14,)
This is a class of Odoo report bugs where the QWeb template, the report action, and wkhtmltopdf interact in subtle ways. Applies to Odoo 17.0/18.0/19.0.
Quick Fix
Test with HTML output to isolate. Add &report_type=qweb-html to the report URL:
/report/pdf/sale.report_saleorder/14 → blank PDF
/report/html/sale.report_saleorder/14 → HTML, also blank?
If HTML is blank too, the QWeb template is wrong. If HTML is fine but PDF is blank, wkhtmltopdf is the problem.
For the wkhtmltopdf case, ensure the binary version is correct (Odoo 17.0/18.0/19.0 require wkhtmltopdf 0.12.6 with patched Qt):
wkhtmltopdf --version
# wkhtmltopdf 0.12.6 (with patched qt)
# If wrong, install the right one:
wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-3/wkhtmltox_0.12.6.1-3.jammy_amd64.deb
sudo dpkg -i wkhtmltox_0.12.6.1-3.jammy_amd64.deb
Why This Happens
Odoo PDF reports go: QWeb template renders to HTML → Odoo passes HTML to wkhtmltopdf → wkhtmltopdf converts to PDF. The five common failure modes:
- wkhtmltopdf wrong version. Odoo bundles assumptions about
0.12.6 (with patched qt). Other versions (0.12.5, 0.12.7) silently produce blank pages or distort layouts. - CSS that wkhtmltopdf cannot parse. CSS Grid, modern Flex,
@containerqueries, and someposition: fixedpatterns render blank in wkhtmltopdf. - Network-blocked external assets. The report references
https://example.com/font.woffand the Odoo server cannot reach example.com — the resource fails silently and content using that font collapses. <t t-call="web.external_layout">outside a<t t-name="...">wrapper. The layout renders but the inner content is in the wrong scope.- Empty record set. The report iterates
o in docsbutdocsis empty due to a domain bug — the page renders zero records, looks blank.
Step-by-Step Diagnosis
1. Check wkhtmltopdf version.
wkhtmltopdf --version
Required: 0.12.6 (with patched qt). Anything else, install the right one.
2. Render to HTML in dev.
http://localhost:8069/report/html/sale.report_saleorder/14?debug=1
Inspect the rendered HTML. If it is blank, the template is the problem. If it has content, wkhtmltopdf is the problem.
3. Test wkhtmltopdf directly. Save the rendered HTML to a file, then:
wkhtmltopdf --enable-local-file-access page.html out.pdf
If the PDF is still blank, the HTML's CSS or external assets are the cause.
4. Check for CSS incompatibilities. wkhtmltopdf does NOT support:
- CSS Grid (use Flexbox)
- CSS variables in some contexts
position: sticky- Some
@mediaquery forms - ES6+ JavaScript (it runs an old WebKit)
5. Check the report action.
action = env.ref('sale.action_report_saleorder')
print(action.report_type) # 'qweb-pdf' or 'qweb-html'
print(action.report_name) # the QWeb template id
print(action.binding_model_id) # which model triggers this
Permanent Fix
For wkhtmltopdf version, install the exact version Odoo requires:
# Ubuntu 22.04 / Debian 12
wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-3/wkhtmltox_0.12.6.1-3.jammy_amd64.deb
sudo apt install -y ./wkhtmltox_0.12.6.1-3.jammy_amd64.deb
# Verify
wkhtmltopdf --version
Pin this version in your provisioning scripts so future server rebuilds keep it.
For CSS incompatibilities, write report CSS for wkhtmltopdf, not for browsers:
/* Avoid: CSS Grid */
.row { display: grid; grid-template-columns: 1fr 1fr; }
/* Use: Float / Flexbox / Tables */
.row::after { content: ""; clear: both; display: table; }
.col { float: left; width: 50%; }
/* Or use an HTML table for layout — wkhtmltopdf renders tables flawlessly */
For complex multi-page layouts, use HTML tables or Bootstrap 5's grid (which Odoo bundles and is wkhtmltopdf-tested).
For external assets, ensure the Odoo server can reach them or inline them. Production servers behind strict egress firewalls often cannot reach Google Fonts; use Odoo's bundled fonts instead:
<style>
body { font-family: 'Roboto', 'Helvetica', sans-serif; }
</style>
Only reference fonts that ship with the Odoo image.
For the <t t-call="web.external_layout"> issue, wrap correctly:
<template id="report_priority_document">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="o">
<t t-call="web.external_layout">
<div class="page">
<h2>Priority Order: <span t-field="o.name"/></h2>
<p>Customer: <span t-field="o.partner_id.name"/></p>
<!-- content -->
</div>
</t>
</t>
</t>
</template>
Both web.html_container and web.external_layout are required wrappers. Missing either breaks rendering subtly.
For empty docs, debug the iteration:
<t t-foreach="docs" t-as="o">
<p>Document <t t-esc="o.id"/></p> <!-- temporary debug -->
...
</t>
If you see no debug output, docs is empty. Check the report action's _get_report_values in the model.
How to Prevent It
- Pin wkhtmltopdf in deploy scripts. Every Odoo server's provisioning installs exactly version
0.12.6.1-3 (with patched qt). No silent OS upgrades. - CI test that PDFs render non-blank. A simple test that downloads a PDF, checks its byte size is above a threshold (PDFs of one blank page are ~3 KB; a real one is 30+ KB). Catches blank-page regressions cheaply.
- Avoid modern CSS in reports. Report templates use the same CSS conventions as Odoo's official
web.external_layout. When in doubt, copy from Odoo's own reports. - Inline external assets. Embed images as base64, fonts as base64-encoded WOFF in CSS. Reduces rendering risk to zero.
- Test with the real wkhtmltopdf, not the browser preview. Browser preview shows the HTML; wkhtmltopdf is what creates the PDF. Surface bugs by always validating the actual PDF output during dev.
- Use the
--debug-javascriptflag during dev. Lets you see JS errors that wkhtmltopdf would otherwise eat.
Related Errors
- wkhtmltopdf protocol error — close cousin, same toolchain.
- QWeb template not found at runtime — pre-render failure mode.
- Report translations missing — report renders but in wrong language.
- Page break not working — sibling layout bug.
Frequently Asked Questions
Why does Odoo bundle a specific wkhtmltopdf version?
The official wkhtmltopdf project went unmaintained around 2022. Odoo (and many other projects) standardized on the last known-good "with patched qt" build (0.12.6) because newer releases broke compatibility and security. Until a successor exists (or Odoo migrates to weasyprint or chromium-headless), 0.12.6 is the answer.
Can I switch to a different PDF renderer?
Possible but invasive. The OCA report_xlsx and report_qweb_pdf_chromium modules offer alternatives. Chromium-based rendering supports modern CSS but adds a heavy dependency. Stick with wkhtmltopdf unless you have a specific layout that demands modern CSS.
My report is fine on Linux but blank on Windows dev. Why?
The Windows wkhtmltopdf binary is sometimes a different version. Use Docker or WSL2 to develop against the same wkhtmltopdf as production. Consistency wins.
Why does the same template render blank for some users?
ACL. The user does not have read access to one of the records the template iterates. The template silently iterates an empty recordset for that user, producing a blank page. Add a guard or grant the necessary read access.
How do I add custom CSS only to one report?
Two patterns. Inline <style> inside the template's <t t-call="web.html_container"> block — scoped to that template's render. Or define a separate asset bundle and reference it from a custom paperformat. Inline is simpler and avoids global side effects.
My PDF is huge — 50 MB for a one-page invoice. Why?
Almost always embedded images at full resolution. wkhtmltopdf does not auto-downsample. Resize images before storing or before referencing in the template. A logo at 300 DPI for a print-only PDF is reasonable; 4K screenshots embedded as-is are not.
Need help with a tricky Odoo error? ECOSIRE's Odoo experts have shipped 215+ modules — get expert help.
作者
ECOSIRE TeamTechnical Writing
The ECOSIRE technical writing team covers Odoo ERP, Shopify eCommerce, AI agents, Power BI analytics, GoHighLevel automation, and enterprise software best practices. Our guides help businesses make informed technology decisions.
相关文章
如何将自定义按钮添加到 Odoo 表单视图 (2026)
将自定义操作按钮添加到 Odoo 19 表单视图:Python 操作方法、视图继承、条件可见性、确认对话框。经过生产测试。
如何在没有 Studio 的情况下在 Odoo 中添加自定义字段 (2026)
通过 Odoo 19 中的自定义模块添加自定义字段:模型继承、视图扩展、计算字段、存储/非存储决策。代码优先,版本控制。
如何使用外部布局在 Odoo 中添加自定义报告
使用 web.external_layout 在 Odoo 19 中构建品牌 PDF 报告:QWeb 模板、paperformat、操作绑定。带有印刷徽标+页脚覆盖。