On this page
The short answer
BR-O-09 fails when a cac:TaxSubtotal in category O has a cbc:TaxAmount other than zero; the recorded invoice charges 5.00, which is 20% of its out-of-scope line of 25.00. Set the breakdown tax amount to 0.00 and take the 5.00 out of cac:TaxTotal/cbc:TaxAmount, cbc:TaxInclusiveAmount and cbc:PayableAmount, which brings the amount due back to 25.00.
If the buyer really owes VAT on the amount, the supply is not outside the scope of VAT. Then the category is what is wrong, and a document that charges VAT cannot be expressed with O at all.
What the rule checks
The rule compares the cbc:TaxAmount beside each O cac:TaxCategory under the VAT scheme with zero, as a number: 0 passes as well as 0.00, and a negative amount fails like a positive one, as -5.00 did when tried.
BR-CO-17 only catches the larger amounts, because an O breakdown normally has no cbc:Percent, and for a breakdown without a rate that rule asks only for a tax amount that rounds to zero as a whole number. When tried, 0.40 in the O breakdown reported this rule alone, and 0.50 brought BR-CO-17 back.
The VAT total is compared by a different rule. With 5.00 in the O breakdown and the VAT total left at 0.00, the document reported BR-CO-14 as well as this rule and BR-CO-17 when tried.
| Term | Meaning | UBL element |
|---|---|---|
| BT-117 | VAT category tax amount | cac:TaxTotal/cac:TaxSubtotal/cbc:TaxAmount |
| BT-118 | VAT category code | cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:ID |
| BT-110 | Invoice total VAT amount | cac:TaxTotal/cbc:TaxAmount |
How an integration ends up here
Possible causes, from the shape of the rule rather than from measured usage:
- Tax is calculated at the default Standard rate for every breakdown, whatever its category.
- An invoice that used to be Standard rated was moved to
Oby relabelling the category, and the stored tax figures were kept. - The supplier is not registered for VAT, but its invoicing software was set up with VAT switched on.
- The document VAT is calculated once and then attributed to the only breakdown there is, the
Oone.
How to fix it
- Confirm that the amounts in the breakdown are outside the scope of VAT. If they are, no VAT is due on them and the breakdown tax amount is
0.00. - Set
cbc:TaxAmountin theOcac:TaxSubtotalto0.00. - Recalculate the VAT total as the sum of the breakdown tax amounts, then the total with VAT and the amount due: in the recorded example the VAT total falls from 5.00 to 0.00, and both other totals from 30.00 to 25.00.
- If VAT is due after all, move the lines to the category that applies, with its rate, and replace the
Obreakdown and its reason with that category's breakdown; the VAT identifiers thatBR-O-02forbade can then return.
Validate your corrected invoice
Before and after
These are fragments, not complete documents. The complete synthetic documents they come from are linked below.
Fragment of the failing invoice: 5.00 of VAT in the O breakdown, carried into the totals
<cac:TaxTotal>
<cbc:TaxAmount currencyID="GBP">5.00</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="GBP">25.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="GBP">5.00</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>O</cbc:ID>
<cbc:TaxExemptionReasonCode>VATEX-EU-O</cbc:TaxExemptionReasonCode>
<cbc:TaxExemptionReason>Not subject to VAT</cbc:TaxExemptionReason>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>
<cac:LegalMonetaryTotal>
<cbc:LineExtensionAmount currencyID="GBP">25.00</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount currencyID="GBP">25.00</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount currencyID="GBP">30.00</cbc:TaxInclusiveAmount>
<!-- allowance, charge, prepaid and rounding totals omitted from this fragment -->
<cbc:PayableAmount currencyID="GBP">30.00</cbc:PayableAmount>
</cac:LegalMonetaryTotal>Fragment of the corrected invoice: no VAT in the O breakdown, and 25.00 due
<cac:TaxTotal>
<cbc:TaxAmount currencyID="GBP">0.00</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="GBP">25.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="GBP">0.00</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>O</cbc:ID>
<cbc:TaxExemptionReasonCode>VATEX-EU-O</cbc:TaxExemptionReasonCode>
<cbc:TaxExemptionReason>Not subject to VAT</cbc:TaxExemptionReason>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>
<cac:LegalMonetaryTotal>
<cbc:LineExtensionAmount currencyID="GBP">25.00</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount currencyID="GBP">25.00</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount currencyID="GBP">25.00</cbc:TaxInclusiveAmount>
<!-- allowance, charge, prepaid and rounding totals omitted from this fragment -->
<cbc:PayableAmount currencyID="GBP">25.00</cbc:PayableAmount>
</cac:LegalMonetaryTotal>The failing invoice shows 5.00 as the O breakdown tax amount and as the VAT total, and 30.00 as cbc:TaxInclusiveAmount and cbc:PayableAmount; the corrected invoice has 0.00 and 25.00. Beside BR-O-09, the failing document reports BR-CO-17: with no rate in the O breakdown, that rule expects the tax amount to round to 0, and 5.00 does not.
What the validator reported
- The failing invoice reports BR-CO-17 and BR-O-09. The corrected document passes every layer with no findings.Download the failing XMLDownload the corrected XML
Recorded on phive 12.1.0 / phive-rules-peppol 4.5.6 / Saxon-HE 12.10, the engine behind the free validator, using synthetic data. A recorded result is regression evidence for these documents; it is not a certification.
Where it applies
- Applies to UBL
InvoiceandCreditNote; as a credit note the failing invoice reported this rule andBR-CO-17again when tried. - Only
Obreakdowns under theVATscheme are tested. The Zero rated, exempt, reverse-charge, intra-community and export categories each have a nil tax amount rule of their own. - The breakdown's other values are checked elsewhere: its taxable amount by
BR-O-08and its reason byBR-O-10.
Related rules
- BR-CO-17 is reported with this rule, and only flags an O tax amount that does not round to zero
- BR-O-08 checks the taxable amount of the same O breakdown
- BR-E-09 is the zero tax amount rule for exempt breakdowns
- BR-O-01 requires this breakdown to appear exactly once
- Browse every rule in the reference
- Background: Understanding EN 16931 validation errors
Scope and source
Written for Peppol BIS Billing 3.0.21 (May 2026), EN 16931 1.3.16, as applied to UBL 2.1 Invoice and CreditNote documents. Other profiles, syntaxes and releases can define this identifier differently. Guidance version 2026-09-28.1: source checked 2026-09-28, explanation last updated 2026-09-28.
The official definition of BR-O-09 carries the normative wording and test. This page is our explanation of it, not a copy.
Guidance does not change the engine verdict. Fixing this finding does not mean the document passes every layer, and validation does not certify legal or tax compliance or transmit a document over Peppol.

