odoo/odoo · error · UserError
The sending of invoices is not set up properly, make sure th
Error message
The sending of invoices is not set up properly, make sure the report used is set for invoices.
What it means
_check_invoice_report guards the send/generate flow: it fails when a report passed via custom_settings['pdf_report'] is not available for one of the moves, or when the resolved default report does not have is_invoice_report True. The point is that invoice sending must use a report declared as an invoice report (correct model and paperformat binding).
Source
Thrown at addons/account/models/account_move_send.py:353
@api.model
def _get_move_constraints(self, move):
constraints = {}
if move.state != 'posted':
constraints['not_posted'] = _("You can't generate invoices that are not posted.")
if not move.is_sale_document(include_receipts=True):
constraints['not_sale_document'] = _("You can only generate sales documents.")
return constraints
@api.model
def _check_invoice_report(self, moves, **custom_settings):
if ((
custom_settings.get('pdf_report')
and any(not move._is_action_report_available(custom_settings['pdf_report']) for move in moves)
)
or any(not self._get_default_pdf_report_id(move).is_invoice_report for move in moves)
):
raise UserError(_("The sending of invoices is not set up properly, make sure the report used is set for invoices."))
@api.model
def _format_error_text(self, error):
""" Format the error that can be a dict (complex format needed)
:param error: the error to format.
:return: a text formatted error.
"""
errors = '\n- '.join(error.get('errors', ''))
return f"{error['error_title']}\n- {errors}" if errors else error['error_title']
@api.model
def _format_error_html(self, error):
""" Format the error that can be a dict (complex format needed)
:param error: the error to format.
:return: a html formatted error.
"""View on GitHub (pinned to 1e661df964)
Solutions
- Pass a proper invoice report: verify report.is_invoice_report and report.model == 'account.move' before using it in custom_settings.
- Fix the custom report definition so it is registered as an invoice report (binding_model_id account.move / is_invoice_report), then re-run the send.
- If no explicit report is wanted, clear the wrong pdf_report from custom_settings and let defaults resolve.
Example fix
// before
settings = {'pdf_report': generic_report} # not an invoice report
send._send_invoice(move, **settings)
// after
assert generic_report.is_invoice_report and generic_report.model == 'account.move'
settings = {'pdf_report': generic_report}
send._send_invoice(move, **settings) Defensive patterns
Strategy: validation
Validate before calling
report = custom_settings.get('pdf_report') or env['account.move.send']._get_default_pdf_report_id(move)
assert report.is_invoice_report and all(move._is_action_report_available(report) for move in moves) Prevention
- Whitelist reports in integrations: model 'account.move' + is_invoice_report True.
- Test the send wizard after any report customization.
- Do not pass generic document reports into invoice sending.
When it happens
Trigger: Calling account.move.send actions with custom_settings {'pdf_report': some_report} where some_report is unavailable for a move, or default template resolution (see error 135) returning a report with is_invoice_report False — e.g. a generic document report bound to another model.
Common situations: Integrations passing an arbitrary ir.actions.report id to the send wizard; custom PDF report modules that forget to set the invoice report flag / binding model account.move; mixing refund or delivery-slip reports into invoice sending.
Related errors
- There is no template that applies to this move type.
- Account %s cannot be unmerged as it already belongs to a sin
- Account Groups with the same granularity can't overlap
- The journal item is not linked to the correct financial acco
- A statement should only contain lines from the same journal.
AI-assisted analysis of odoo/odoo@1e661df964 (2026-08-15).
Data as JSON: /api/errors/d0f9b2c0202bbeb0.
Report an issue: GitHub.