The short answer
BR-53 fails when the document declares a VAT accounting currency in cbc:TaxCurrencyCode and no cac:TaxTotal/cbc:TaxAmount has that currency in its currencyID. Add a second cac:TaxTotal directly under the root that holds only a cbc:TaxAmount, with currencyID set to the accounting currency and the VAT total converted into it.
If the seller accounts for VAT in the invoice currency, the fix runs the other way: remove cbc:TaxCurrencyCode. It is optional, and belongs only on a document whose VAT must be accounted for in a currency other than the one it is issued in.
What the rule checks
The rule runs once on the document root. For the cbc:TaxCurrencyCode there, it looks for a cbc:TaxAmount that is a direct child of a cac:TaxTotal and whose currencyID is the same code. Tax amounts inside a cac:TaxSubtotal do not count, and the order of the tax totals does not matter.
A document without cbc:TaxCurrencyCode gives the rule nothing to look for, so it passes.
Only the currency is matched. The amount is not examined: no rule converts the invoice VAT total or checks an exchange rate, and when tried, an accounting-currency total of 0.00 beside 5.00 of VAT in the invoice currency passed every layer.
The code and the currencyID are matched exactly as written. When tried, a cbc:TaxCurrencyCode with spaces around EUR, beside a correct EUR total, reported this rule and nothing else. A lower-case eur also brought BR-CL-05, the currency code list rule, and PEPPOL-EN16931-R055.
| Term | Meaning | UBL element |
|---|---|---|
| BT-6 | VAT accounting currency code | cbc:TaxCurrencyCode |
| BT-111 | Invoice total VAT amount in accounting currency | cac:TaxTotal/cbc:TaxAmount (in the tax total without cac:TaxSubtotal, currencyID equal to BT-6) |
| BT-110 | Invoice total VAT amount | cac:TaxTotal/cbc:TaxAmount (in the tax total that holds the VAT breakdown) |
How an integration ends up here
Possible causes, from the shape of the rule rather than from measured usage:
- The accounting currency code is filled from a company setting on every document, while the converted VAT total is written only when a conversion was actually made.
- The serialiser writes a single
cac:TaxTotaland has no place for a second one, so the converted figure is lost. - The converted amount is written with the invoice currency, or another currency, in its
currencyID. When tried with the invoice currency,BR-CO-15came too, because it expects exactly one VAT total in the invoice currency. - The code is written in lower case or with padding, so it no longer matches the
currencyIDof the amount.
How to fix it
- Decide whether the document needs a VAT accounting currency at all. If the seller accounts for VAT in the invoice currency, remove
cbc:TaxCurrencyCodeand stop here. - Otherwise take the invoice VAT total, the
cbc:TaxAmountof thecac:TaxTotalthat holds the breakdown, and convert it into the accounting currency at the rate your VAT accounting requires. The rate comes from your accounting rules; the validator does not check it. - Add a second
cac:TaxTotaldirectly under the root containing onlycbc:TaxAmount, withcurrencyIDequal to thecbc:TaxCurrencyCodevalue and the converted amount rounded to two decimals. A third decimal bringsUBL-DT-01. Give this total nocac:TaxSubtotal: the breakdown stays in the invoice currency. - Write the code and the
currencyIDas the same upper-case ISO 4217 code without spaces, and keep the converted amount on the same side of zero as the invoice VAT total, whichPEPPOL-EN16931-R055checks.
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: EUR is declared as the accounting currency, but the only tax total is in GBP
<cbc:DocumentCurrencyCode>GBP</cbc:DocumentCurrencyCode>
<cbc:TaxCurrencyCode>EUR</cbc:TaxCurrencyCode>
<!-- buyer reference and parties omitted from this fragment -->
<cac:TaxTotal>
<cbc:TaxAmount currencyID="GBP">5.00</cbc:TaxAmount>
<!-- VAT breakdown omitted from this fragment -->
</cac:TaxTotal>
<cac:LegalMonetaryTotal>
<!-- monetary totals omitted from this fragment -->
</cac:LegalMonetaryTotal>Fragment of the corrected invoice: a second tax total states the VAT in EUR
<cbc:DocumentCurrencyCode>GBP</cbc:DocumentCurrencyCode>
<cbc:TaxCurrencyCode>EUR</cbc:TaxCurrencyCode>
<!-- buyer reference and parties omitted from this fragment -->
<cac:TaxTotal>
<cbc:TaxAmount currencyID="GBP">5.00</cbc:TaxAmount>
<!-- VAT breakdown omitted from this fragment -->
</cac:TaxTotal>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="EUR">5.80</cbc:TaxAmount>
</cac:TaxTotal>
<cac:LegalMonetaryTotal>
<!-- monetary totals omitted from this fragment -->
</cac:LegalMonetaryTotal>The corrected invoice has a second cac:TaxTotal holding only a cbc:TaxAmount of 5.80 in EUR; the failing one declares EUR as its accounting currency and has no amount in it. Two Peppol rules report the same gap. PEPPOL-EN16931-R054 fires because a declared accounting currency needs exactly one tax total without a breakdown and there is none. PEPPOL-EN16931-R055 fires because it compares the signs of the two VAT totals and cannot find the EUR one. Restoring the EUR total clears all three. The 5.80 is an illustrative figure: nothing checks it against the 5.00 in GBP.
What the validator reported
- The failing invoice reports BR-53, PEPPOL-EN16931-R054 and PEPPOL-EN16931-R055. 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. A credit note declaring EUR with no EUR tax total reported the same three rules when tried. - Reported by the EN 16931 layer. The Peppol layer adds
PEPPOL-EN16931-R054andPEPPOL-EN16931-R055for the same gap, andPEPPOL-EN16931-R005when the declared accounting currency is the invoice currency. - The accounting-currency amount is left out of the Peppol requirement that every
currencyIDequals the invoice currency, because it sits in a tax total without a breakdown. A breakdown in the accounting currency is not accepted; that case is described underPEPPOL-EN16931-R054. - A
cbc:TaxCurrencyCodethat is not a valid ISO 4217 code is reported byBR-CL-05.
Related rules
- PEPPOL-EN16931-R054 requires exactly one tax total without a breakdown when the accounting currency is declared, and none otherwise
- PEPPOL-EN16931-R055 checks that this amount has the same sign as the VAT total in the invoice currency
- PEPPOL-EN16931-R005 rejects an accounting currency that is the same as the invoice currency
- PEPPOL-EN16931-R051 requires the invoice currency on every other amount in the document
- 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-24.1: source checked 2026-09-24, explanation last updated 2026-09-24.
The official definition of BR-53 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.
