Skip to content

BR-CO-18Add the missing VAT breakdown to the tax total

Every invoice and credit note needs at least one VAT breakdown: a TaxSubtotal inside a document-level TaxTotal.

EN 16931Fatal: the document is invalidVATTotals

The short answer

BR-CO-18 fails when the document has no cac:TaxSubtotal inside a cac:TaxTotal directly under the root. Add one cac:TaxSubtotal for each VAT category and rate used on the lines and the document-level allowances and charges, with its taxable amount, tax amount and cac:TaxCategory.

A cac:TaxTotal that carries only the overall cbc:TaxAmount is not enough, even when that amount is correct.

What the rule checks

This is a presence check on the document root: at least one cac:TaxTotal/cac:TaxSubtotal must exist. It does not look inside the breakdown; the amounts and the category are checked by other rules.

The XSD accepts a cac:TaxTotal without any cac:TaxSubtotal, and a document without a cac:TaxTotal at all, so the omission is first reported here rather than by the schema layer.

A document with no VAT to pay still needs a breakdown. An exempt invoice with a VAT total of 0.00 fails this rule once its cac:TaxSubtotal is removed.

TermMeaningUBL element
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 mapping writes the VAT total from a header field and never builds the per-category breakdown.
  • The breakdown is generated only when the VAT amount is above zero, so zero-rated, exempt or reverse-charge documents lose it.
  • The source grouping by VAT category returns no rows, for example because lines have no tax code assigned, and the loop that writes cac:TaxSubtotal emits nothing.
  • The breakdown is written into a cac:TaxTotal under each line instead of the document-level cac:TaxTotal. Only breakdowns directly under the root count.

How to fix it

  1. Group the line net amounts, document-level allowances and document-level charges by VAT category code and rate.
  2. For each group write a cac:TaxSubtotal with cbc:TaxableAmount, cbc:TaxAmount and a cac:TaxCategory holding cbc:ID, cbc:Percent and cac:TaxScheme/cbc:ID of VAT. Some categories also need an exemption reason.
  3. Put the breakdowns in the cac:TaxTotal that carries the VAT total in the document currency, and make that cbc:TaxAmount the sum of the breakdown tax amounts. BR-CO-14 checks it.
  4. Use the VAT categories the transaction really has. Do not add a breakdown for a category that is not on the lines just to satisfy this rule.

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 tax total has an amount but no breakdown

<cac:TaxTotal>
  <cbc:TaxAmount currencyID="GBP">5.00</cbc:TaxAmount>
</cac:TaxTotal>

Fragment of the corrected invoice: one standard-rated breakdown for the single line of 25.00

<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>S</cbc:ID>
      <cbc:Percent>20</cbc:Percent>
      <cac:TaxScheme>
        <cbc:ID>VAT</cbc:ID>
      </cac:TaxScheme>
    </cac:TaxCategory>
  </cac:TaxSubtotal>
</cac:TaxTotal>

The corrected document has the cac:TaxSubtotal that the failing one lacks; nothing else differs. The failing document also reports BR-S-01, because its line is standard rated and no standard-rated breakdown exists, and two Peppol findings about the shape of the tax totals: PEPPOL-EN16931-R053, because no tax total carries a breakdown, and PEPPOL-EN16931-R054, because a tax total without a breakdown is present although no VAT accounting currency is declared. Restoring the breakdown clears all four.

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 alike; a credit note with its only breakdown removed reports the same four findings.
  • The category rule that accompanies this finding depends on the VAT categories in the document. The recorded example is standard rated and reports BR-S-01; an exempt invoice reports the corresponding exempt-category rule instead.
  • BR-CO-14 stays silent in this situation. It skips a tax total that has no breakdown, so the VAT total is not compared with a breakdown until one is back.
  • An empty cac:TaxSubtotal element is no way round the rule: the XSD layer rejects it and the later layers are skipped.

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-20.1: source checked 2026-09-20, explanation last updated 2026-09-20.

The official definition of BR-CO-18 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.