The Missing Report Problem
You built a custom QWeb report, upgraded the module, but the report does not appear in the Print menu. Or it appears but renders blank. Or it throws a cryptic error when you try to generate the PDF. Custom reports in Odoo require several components working together, and a problem in any one of them breaks the entire report.
Report Architecture
A working Odoo report requires:
- ir.actions.report record — defines the report action, model binding, and output format
- QWeb template — the HTML template for the report content
- Paper format (optional) — page size, margins, orientation
- wkhtmltopdf — converts HTML to PDF
Problem 1: Report Not in Print Menu
# The report action exists but does not show in the Print menu
# Cause 1: binding_model_id not set
# The report must be bound to a model to appear in its Print menu
# Fix: Check the report action definition:
<record id="report_custom_invoice" model="ir.actions.report">
<field name="name">Custom Invoice</field>
<field name="model">account.move</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">my_module.report_custom_invoice_template</field>
<!-- THIS IS REQUIRED for Print menu binding -->
<field name="binding_model_id" ref="account.model_account_move"/>
<field name="binding_type">report</field>
</record>
# Cause 2: Module not upgraded after adding the report
# Fix: Upgrade the module: -u my_module
# Cause 3: Report bound to wrong model
# A report bound to 'sale.order' won't appear on invoices
# Verify the model matches where you expect the Print buttonProblem 2: Report Renders Blank PDF
# PDF downloads but all pages are blank
# Cause 1: wkhtmltopdf issue (see report URL timeout guide)
# Quick fix: Set report.url system parameter
# Settings → Technical → System Parameters
# Key: report.url Value: http://127.0.0.1:8069
# Cause 2: Template name mismatch
# report_name in ir.actions.report must match template id
<!-- In report action: -->
<field name="report_name">my_module.report_template</field>
<!-- Template must have matching id: -->
<template id="report_template">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="doc">
<t t-call="web.external_layout">
<div class="page">
<h1><t t-esc="doc.name"/></h1>
</div>
</t>
</t>
</t>
</template>
# Note: template id becomes my_module.report_template
# The report_name must be exactly thisProblem 3: Template Rendering Error
# Error in logs:
# ValueError: External ID not found: my_module.report_template
# Or: QWebException: 'NoneType' object has no attribute 'name'
# Cause 1: Template XML file not in __manifest__.py
# Fix: Add the template file to the 'data' list:
'data': [
'reports/custom_report.xml',
],
# Cause 2: Field access error — doc.field_name doesn't exist
# Fix: Verify all field names in the template match the model
# Common: typos, accessing Many2one without .name, wrong field type
# Cause 3: Accessing a related field without checking for None
# BAD:
<t t-esc="doc.partner_id.commercial_partner_id.vat"/>
# If partner_id is empty, this crashes
# FIX:
<t t-if="doc.partner_id">
<t t-esc="doc.partner_id.commercial_partner_id.vat"/>
</t>Problem 4: Wrong Paper Format
# Report prints but layout is wrong — margins too big, content cut off
# Fix: Define and assign a paper format:
<record id="paperformat_custom" model="report.paperformat">
<field name="name">Custom A4</field>
<field name="format">A4</field>
<field name="orientation">Portrait</field>
<field name="margin_top">25</field>
<field name="margin_bottom">20</field>
<field name="margin_left">7</field>
<field name="margin_right">7</field>
<field name="header_spacing">20</field>
<field name="dpi">90</field>
</record>
# Assign to report:
<record id="report_custom_invoice" model="ir.actions.report">
<field name="paperformat_id" ref="paperformat_custom"/>
</record>Problem 5: Header/Footer Not Showing
# Report content shows but no company header or footer
# Cause: Not using web.external_layout
# Fix: Wrap report content in external_layout:
<template id="report_template">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="doc">
<t t-call="web.external_layout">
<div class="page">
<!-- Report content here -->
</div>
</t>
</t>
</t>
</template>
# web.external_layout adds the company header and footer
# web.html_container provides the base HTML structureProblem 6: Report Works in HTML But Not PDF
# HTML preview (qweb-html) works, but PDF generation fails
# Test HTML version:
# Change report_type temporarily:
<field name="report_type">qweb-html</field>
# Generate the report → if HTML works, the issue is wkhtmltopdf
# Common wkhtmltopdf issues:
# 1. CSS not supported by wkhtmltopdf (flexbox, grid, modern CSS)
# Fix: Use tables and floats for layout
# 2. External fonts not loading
# Fix: Embed fonts or use web-safe fonts
# 3. Images not loading (relative URLs)
# Fix: Use absolute URLs or base64-encoded imagesDebugging Reports
# 1. Check if report action exists:
# Settings → Technical → Actions → Reports
# Search for your report name
# 2. Preview HTML version:
# Navigate to: /report/html/my_module.report_template/RECORD_ID
# This shows the HTML that wkhtmltopdf will convert
# 3. Check template exists:
# In Odoo shell:
env.ref('my_module.report_template')
# Should return the template record without error
# 4. Enable report debug logging:
./odoo-bin --log-handler=odoo.addons.base.models.ir_actions_report:DEBUG