Skip to content

PEPPOL-EN16931-R054: Send a tax total without a breakdown only with a VAT accounting currency

A cac:TaxTotal with no cac:TaxSubtotal must appear exactly once when cbc:TaxCurrencyCode is given, and not at all when it is absent.

Peppol BIS BillingFatal: the document is invalidVATTotals

The short answer

PEPPOL-EN16931-R054 counts the cac:TaxTotal elements directly under the root that contain no cac:TaxSubtotal. With cbc:TaxCurrencyCode present there must be exactly one, carrying the VAT total in the accounting currency; without it there must be none. In the recorded example a EUR tax total is present but the code declaring EUR as the accounting currency is not, so either add cbc:TaxCurrencyCode or remove the extra total.

Which of the two is right is a business fact, not something the validator can decide. Keep the second total only if the seller really accounts for VAT in that currency.

What the rule checks

The rule runs once per document. A tax total is counted when it is a direct child of the root and has no cac:TaxSubtotal child at all; the tax total that holds the VAT breakdown is never counted.

The expected count is 1 when cbc:TaxCurrencyCode exists and 0 when it does not. The currency of the counted total is not examined here, so a spare total in the invoice currency counts the same as one in the accounting currency; when tried without cbc:TaxCurrencyCode, a duplicate GBP total was reported by this rule and by BR-CO-15.

Two totals without a breakdown fail even when both are in the declared currency. A duplicated EUR total beside a cbc:TaxCurrencyCode of EUR reported this rule alone when tried.

The accounting-currency total must not carry a breakdown of its own. When tried, giving the EUR total a cac:TaxSubtotal left no total without a breakdown, so this rule fired, and PEPPOL-EN16931-R053 (two totals with a breakdown), PEPPOL-EN16931-R051 (EUR amounts where the invoice currency is required) and BR-S-08 came with it.

TermMeaningUBL element
BT-6VAT accounting currency codecbc:TaxCurrencyCode
BT-111Invoice total VAT amount in accounting currencycac:TaxTotal/cbc:TaxAmount (in the tax total without cac:TaxSubtotal)
BG-23VAT breakdowncac:TaxTotal/cac:TaxSubtotal

How an integration ends up here

Possible causes, from the shape of the rule rather than from measured usage:

  • The converted VAT total is written whenever the source record holds one, while cbc:TaxCurrencyCode depends on a separate setting that is off.
  • The VAT total is emitted twice: once in the tax total with the breakdown and again as a bare tax total in the invoice currency.
  • The accounting currency is declared, but the serialiser only ever emits one cac:TaxTotal, so the converted amount never appears.
  • The converted VAT is broken down by category like the main total instead of being sent as a single amount.

How to fix it

  1. Establish whether the seller accounts for VAT in a currency other than the invoice currency.
  2. If so, write that currency code to cbc:TaxCurrencyCode, straight after cbc:DocumentCurrencyCode, and keep exactly one extra cac:TaxTotal containing only cbc:TaxAmount with that code as its currencyID.
  3. If not, delete every cac:TaxTotal that has no cac:TaxSubtotal. The VAT total in the invoice currency belongs in the tax total that holds the breakdown.
  4. Do not give the accounting-currency total a breakdown, and do not write it twice.

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 EUR tax total without a breakdown, but no VAT accounting currency declared

<cbc:DocumentCurrencyCode>GBP</cbc:DocumentCurrencyCode>
<cbc:BuyerReference>BUYER-REF-001</cbc:BuyerReference>
<!-- 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>

Fragment of the corrected invoice: EUR is declared as the VAT accounting currency

<cbc:DocumentCurrencyCode>GBP</cbc:DocumentCurrencyCode>
<cbc:TaxCurrencyCode>EUR</cbc:TaxCurrencyCode>
<cbc:BuyerReference>BUYER-REF-001</cbc:BuyerReference>
<!-- 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>

The corrected invoice adds <cbc:TaxCurrencyCode>EUR</cbc:TaxCurrencyCode> after the document currency; both tax totals are identical in the two documents. The failing document reports only PEPPOL-EN16931-R054. With no accounting currency declared, BR-53 and PEPPOL-EN16931-R055 have nothing to test, and PEPPOL-EN16931-R051 leaves tax totals without a breakdown out of its currency check, so the stray EUR amount is caught by this rule alone. Removing the EUR total instead would also have passed.

What the validator reported

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 Invoice and CreditNote. A credit note with a EUR tax total and no cbc:TaxCurrencyCode reported this rule alone when tried.
  • Reported by the Peppol layer. Beside it, BR-53 and PEPPOL-EN16931-R055 appear when the accounting currency is declared but its total is missing, and PEPPOL-EN16931-R005 when the declared accounting currency is the invoice currency itself.
  • A document whose only cac:TaxTotal has no breakdown reports this rule with BR-CO-18, PEPPOL-EN16931-R053 and the category rule for its lines: that single total counts as one without a breakdown.

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-R054 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.