Skip to main content
EN 16931 · lines

Error UBL-SR-48: an invoice line with two taxes or none

In a European e-invoice every line carries one VAT category, and only one. In Odoo a line can have several taxes or none, so the clash is common: it is UBL-SR-48 in the file, and Odoo stops it before generating with its own message. BR-CO-04, BR-25 and BR-16 belong to the same group.

FlexigoTech · Editor in charge: Víctor Gómez · Updated 4 November 2026

Key facts

Versions
Odoo 17, 18, 19 and 20
Checked
in the module's source code, version 17.0 and 20.0 · against the sources linked at the end
Reading time
3 min

What each rule says

All four are fatal in the EN 16931 Schematron (validation-1.3.17):

UBL-SR-48
“Invoice lines shall have one and only one classified tax category.” A UBL syntax rule: one line, one category.
BR-CO-04
“Each Invoice line (BG-25) shall be categorized with an Invoiced item VAT category code (BT-151).” The other side: no line without a category.
BR-25
“Each Invoice line (BG-25) shall contain the Item name (BT-153).” Every line with a name.
BR-16
“An Invoice shall have at least one Invoice line (BG-25)” At least one line.
Card for EN 16931 rule UBL-SR-48
One VAT category per line (BT-151), with BR-CO-04, BR-25 and BR-16.

Odoo's message

Odoo does not wait for the validator. Before generating the UBL it walks the lines and, if one does not have exactly one tax, stops with: “Each invoice line shall have one and only one tax.” It happens in all four versions, with a nuance:

  • Odoo 17: it counts the line's taxes leaving out fixed-amount ones, such as eco-taxes; one must remain.
  • Odoo 18, 19 and 20: it counts the tax categories that will be written on the file's line; there must be one.

In the same step it checks BR-25: a line with no product and no description stops with “Each invoice line should have a product or a label.”

The cases that trigger it

Case in OdooWhat to do
Line with no tax, for instance a recharged expenseGive it the right tax, even if it is 0% or exempt.
Two VAT taxes on the same lineKeep one: if they are two different rates, split the line.
VAT plus a surcharge or withholding on the lineCheck whether that second tax belongs in the e-invoice as a tax or in another way; the right answer depends on your country.
Text line with no product or descriptionWrite the description or turn it into a note.

Odoo sections and notes do not count as lines, so they do not trigger the message.

With our XRechnung and ZUGFeRD module

The module builds the XML with its own code and does not run Odoo's check: a line with no tax or with two reaches the file as it is. We checked it with the KoSIT validator:

  • Line without tax: it goes out without a VAT category. In XRechnung UBL it gives UBL-SR-48, BR-CO-04 and BR-Z-08; in XRechnung CII, the module's default format, BR-CO-04, BR-Z-01 and BR-Z-08.
  • Line with two taxes: in UBL only the first percentage tax is written, but the total with VAT carries both, and BR-CO-15 fires. In CII both go on the line and the total VAT does not match the breakdown, and BR-CO-14 fires.
  • Line with a 0% tax: in UBL it goes out as Z and KoSIT accepts it. In CII it goes out as S, and KoSIT gives BR-S-05, plus BR-Z-01 and BR-Z-08.

Review the taxes on each line before generating.

Odoo 20 invoice with the XRechnung / ZUGFeRD tab of the module
Validation result and Ready to send on the invoice. Odoo 20 screenshot with demo data; the report in the screenshot is a test one.

On Odoo 18, 19 and 20, with the FlexigoTech Cloud subscription, every XRechnung and every ZUGFeRD EN 16931 is validated against the KoSIT rules and the failing rules stay under Validation Errors. On Odoo 17 the published version does not validate: these files go out with no warning.

Steps

  1. Read the message: it tells you whether it is the tax or the line name.
  2. Open the invoice in draft and check the taxes column line by line.
  3. Fix, post and generate the file again.

Keep reading

Errors BR-E-10, BR-AE-10, BR-IC-10 and BR-G-10: the VAT exemption reasonBR-E-10, BR-AE-10, BR-IC-10, BR-G-10 and BR-O-10 require a VAT exemption reason; BR-S-10 and BR-Z-10 forbid it. How Odoo 17, 18, 19 and 20 set it.Error BR-CL-23: the line's unit of measure is not a UN/ECE codeBR-CL-23 requires UN/ECE codes for each line's unit, BR-23 requires a unit and Peppol R130 requires it to match the price unit. Where Odoo 17, 18, 19 and 20 take it from.Error BR-CO-15 in an e-invoice: total with VAT is not net plus VATBR-CO-15, BR-CO-14, BR-CO-16 and BR-CO-17 check that e-invoice totals add up. What each one sums and which ones fail over a single cent.
Checked in the module's source code (version 17.0 and 20.0) and the linked sources

Sources