The short answer
PEPPOL-EN16931-R053 fails when the number of root-level cac:TaxTotal elements that contain a cac:TaxSubtotal is anything other than one. Put every VAT breakdown, one cac:TaxSubtotal per category and rate, in a single cac:TaxTotal whose cbc:TaxAmount is the sum of their tax amounts.
Zero fails as well. A document with no VAT breakdown at all reports this rule beside the EN 16931 rules for the missing breakdown.
What the rule checks
The rule runs once on the root and counts the cac:TaxTotal children that hold at least one cac:TaxSubtotal. It passes only when that count is exactly one.
A cac:TaxTotal without a breakdown is not counted. Peppol allows one of those, and only when cbc:TaxCurrencyCode is present, for the VAT total in the accounting currency; PEPPOL-EN16931-R054 enforces that.
No amounts are compared. The recorded split keeps the figures right, 11.70 and 0.00 adding up to the old VAT total, and is still rejected on the count.
When tried, a document with no cac:TaxTotal reported this rule with BR-CO-15, BR-CO-18 and BR-S-01. One whose only tax total had lost its breakdown reported it with BR-CO-18, BR-S-01 and PEPPOL-EN16931-R054.
| Term | Meaning | UBL element |
|---|---|---|
| BG-23 | VAT breakdown | cac:TaxTotal/cac:TaxSubtotal |
| 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:
- The mapping emits one
cac:TaxTotalper VAT rate, mirroring a source table that holds one tax row per rate. - A loop over tax categories opens and closes the tax total inside the loop instead of once around it.
- VAT in a second currency is sent as a full copy of the breakdown, which makes a second tax total with subtotals.
How to fix it
- Open one
cac:TaxTotaldirectly under the root, after any document-levelcac:AllowanceChargeand beforecac:LegalMonetaryTotal. - Inside it, write one
cac:TaxSubtotalfor each combination of VAT category and rate used in the document. - Set its
cbc:TaxAmountto the sum of the breakdown tax amounts, rounded to two decimals, in the document currency. - If VAT must also be stated in an accounting currency, add
cbc:TaxCurrencyCodeand a secondcac:TaxTotalholding only acbc:TaxAmountin that currency. It carries no breakdown, so it is not counted here.
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: the standard-rated and zero-rated breakdowns sit in two separate tax totals
<cac:TaxTotal>
<cbc:TaxAmount currencyID="GBP">11.70</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="GBP">58.50</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="GBP">11.70</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>20</cbc:Percent>
<!-- tax scheme omitted from this fragment -->
</cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="GBP">0.00</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="GBP">10.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="GBP">0.00</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>Z</cbc:ID>
<cbc:Percent>0</cbc:Percent>
<!-- tax scheme omitted from this fragment -->
</cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>Fragment of the corrected invoice: one tax total of 11.70 holding both breakdowns
<cac:TaxTotal>
<cbc:TaxAmount currencyID="GBP">11.70</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="GBP">58.50</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="GBP">11.70</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>20</cbc:Percent>
<!-- tax scheme omitted from this fragment -->
</cac:TaxCategory>
</cac:TaxSubtotal>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="GBP">10.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="GBP">0.00</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>Z</cbc:ID>
<cbc:Percent>0</cbc:Percent>
<!-- tax scheme omitted from this fragment -->
</cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>The failing invoice closes the tax total after the standard-rated breakdown and opens a second one, with its own VAT total of 0.00, for the zero-rated breakdown; the corrected invoice keeps both breakdowns in one tax total of 11.70. Each tax total still agrees with its own breakdown, so BR-CO-14 passes. The failing document also reports BR-CO-15 from the EN 16931 layer. That rule expects exactly one VAT total in the document currency to add to the total without VAT, finds two, 11.70 and 0.00, and fails on the count, even though 68.50 + 11.70 + 0.00 still equals the total with VAT of 80.20. Merging the tax totals clears both findings.
What the validator reported
- The failing invoice reports BR-CO-15 and PEPPOL-EN16931-R053. 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
InvoiceandCreditNotealike. When tried, a credit note split the same way reported the same two rules. - It is a Peppol BIS rule, and the EN 16931 layer does not count tax totals as such. A split breakdown still fails both layers, because
BR-CO-15reacts to the second VAT total in the document currency. - A second tax total that repeats the breakdown in an accounting currency is counted too. When tried, a EUR copy of the standard-rated breakdown reported this rule,
PEPPOL-EN16931-R051on each of its amounts andPEPPOL-EN16931-R054, among other findings. The accounting currency takes a singlecbc:TaxAmountwithout a breakdown.
Related rules
- BR-CO-15 fails beside this rule because it needs a single VAT total in the document currency
- PEPPOL-EN16931-R054 is the companion rule for the tax total without a breakdown
- BR-CO-14 checks that the VAT total equals the sum of its breakdown
- BR-CO-18 requires at least one VAT breakdown, the case where this rule counts zero
- Browse every rule in the reference
- Background: How Peppol invoice validation actually works
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-24.1: source checked 2026-09-24, explanation last updated 2026-09-24.
The official definition of PEPPOL-EN16931-R053 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.
