The short answer
PEPPOL-EN16931-R051 fails for each amount whose currencyID is not exactly the value of cbc:DocumentCurrencyCode. The finding location is the amount; change its currencyID to the invoice currency, and make sure the figure really is in that currency.
There is one exception. When cbc:TaxCurrencyCode names a VAT accounting currency, the VAT total in that currency goes in a second cac:TaxTotal with no breakdown, and that amount keeps its own currency.
What the rule checks
The rule visits every amount element of the kinds used in an invoice, including cbc:PriceAmount and the amounts of allowances and charges at every level, and compares its currencyID with the text of cbc:DocumentCurrencyCode under the root. The comparison is exact, so case and spaces matter.
The cbc:TaxAmount of a cac:TaxTotal that has no cac:TaxSubtotal is skipped; that is where the accounting-currency VAT total belongs. When tried, a GBP invoice with a cbc:TaxCurrencyCode of EUR and a second tax total of 13.46 EUR validated cleanly.
The exception follows the shape of the tax total, not the declared currency. When tried, a second tax total in EUR that repeated the VAT breakdown was reported by this rule on all three of its amounts, together with PEPPOL-EN16931-R053 and several VAT breakdown rules.
When cbc:DocumentCurrencyCode is missing or empty there is nothing to match, and every amount in the document is reported. The missing code itself is BR-05.
A code that is not on the ISO 4217 list fails this rule too, since it cannot equal a valid document currency; the code list rules BR-CL-03 and PEPPOL-EN16931-CL007 then appear with it.
| Term | Meaning | UBL element |
|---|---|---|
| BT-5 | Invoice currency code | cbc:DocumentCurrencyCode |
| - | Currency of an amount (the currencyID attribute) | currencyID on each amount element, for example cac:InvoiceLine/cac:Price/cbc:PriceAmount/@currencyID |
| BT-6 | VAT accounting currency code | cbc:TaxCurrencyCode |
| BT-111 | Invoice total VAT amount in accounting currency (exempt) | cac:TaxTotal/cbc:TaxAmount, in the cac:TaxTotal that has no cac:TaxSubtotal |
How an integration ends up here
Possible causes, from the shape of the rule rather than from measured usage:
- Prices come from a price list in a different currency from the invoice, and the price element takes the list currency while the totals use the invoice currency.
- The invoice is converted for the buyer, and some amounts are converted and relabelled while others are not.
- The document currency is set per customer on the header, while the
currencyIDattributes are hard-coded in the template. - VAT in a local currency is sent as a full copy of the breakdown instead of a single accounting-currency amount.
How to fix it
- Decide the invoice currency and write it to
cbc:DocumentCurrencyCode. - Express every amount in that currency. If a price comes from a list in another currency, convert it before the line is built; changing only the attribute would leave the wrong figure.
- Fill every
currencyIDfrom the document currency in one place in your mapping. - If VAT must also be stated in a local accounting currency, add
cbc:TaxCurrencyCodeand a secondcac:TaxTotalholding only acbc:TaxAmountin that currency, with nocac:TaxSubtotal.
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: a GBP invoice with its item price in EUR
<cbc:DocumentCurrencyCode>GBP</cbc:DocumentCurrencyCode>
<!-- parties, tax total and monetary totals omitted from this fragment -->
<cac:InvoiceLine>
<cbc:ID>1</cbc:ID>
<cbc:InvoicedQuantity unitCode="C62">2</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="GBP">25.00</cbc:LineExtensionAmount>
<!-- item omitted from this fragment -->
<cac:Price>
<cbc:PriceAmount currencyID="EUR">12.5</cbc:PriceAmount>
<cbc:BaseQuantity unitCode="C62">1</cbc:BaseQuantity>
</cac:Price>
</cac:InvoiceLine>Fragment of the corrected invoice: the item price is in GBP, the invoice currency
<cac:Price>
<cbc:PriceAmount currencyID="GBP">12.5</cbc:PriceAmount>
<cbc:BaseQuantity unitCode="C62">1</cbc:BaseQuantity>
</cac:Price>The only difference is the currencyID on the item price: EUR in the failing invoice and GBP in the corrected one, on an invoice whose currency code is GBP. EUR is a valid ISO 4217 code, so the code list rules stay quiet and the EN 16931 layer passes, leaving this Peppol rule as the only finding. In the recorded example a relabel is the right fix because the price of 12.5 was always meant in pounds. A price that really was in euros would need converting as well.
What the validator reported
- The failing invoice reports PEPPOL-EN16931-R051. 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 with anEURprice on aGBPdocument reported this rule alone. - It is reported by the Peppol layer. In the recorded example the EN 16931 layer passes, because none of its rules compares the currency of an item price with the document currency.
- A wrong currency on the VAT total with the breakdown matters to EN 16931 too. When tried,
EURthere also broughtBR-CO-15, which then finds no VAT total in the document currency. - A second tax total in another currency, sent without
cbc:TaxCurrencyCode, is not reported here: when tried,PEPPOL-EN16931-R054reported it instead.
Related rules
- BR-05 requires the document currency code that every amount is compared with
- BR-CL-03 checks that each currencyID is a valid ISO 4217 code
- PEPPOL-EN16931-R054 governs the second tax total that carries VAT in the accounting currency
- BR-CO-15 needs exactly one VAT total in the document currency
- 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-R051 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.
