# BR-CO-18: Add 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.

- Layer: EN 16931
- Severity: fatal (the document is invalid)
- Topics: VAT, Totals
- Official definition: https://docs.peppol.eu/poacc/billing/3.0/rules/ubl-tc434/BR-CO-18/
- Explanation last updated: 2026-09-20

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

| Term | Meaning | UBL element |
|---|---|---|
| BG-23 | VAT breakdown | `cac: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.

## 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

```xml
<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

```xml
<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

- The failing invoice reports **BR-CO-18**, [BR-S-01](https://ironfang.uk/docs/finance/rules/BR-S-01.md), [PEPPOL-EN16931-R053](https://ironfang.uk/docs/finance/rules/PEPPOL-EN16931-R053.md) and [PEPPOL-EN16931-R054](https://ironfang.uk/docs/finance/rules/PEPPOL-EN16931-R054.md). The corrected document passes every layer with no findings.
  - [Download the failing XML](https://ironfang.uk/finance/rule-examples/BR-CO-18-invalid.xml)
  - [Download the corrected XML](https://ironfang.uk/finance/rule-examples/invoice-minimal.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 `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.

## Related rules

- [BR-S-01 requires a standard-rated breakdown when lines, allowances or charges are standard rated](https://ironfang.uk/docs/finance/rules/BR-S-01.md)
- [BR-CO-14 checks the VAT total against the sum of the breakdown tax amounts](https://ironfang.uk/docs/finance/rules/BR-CO-14.md)
- [BR-CO-17 checks each breakdown tax amount against its taxable amount and rate](https://ironfang.uk/docs/finance/rules/BR-CO-17.md)
- [BR-S-08 checks the taxable amount of a standard-rated breakdown against the lines, allowances and charges](https://ironfang.uk/docs/finance/rules/BR-S-08.md)

## 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-20.

[The official definition of BR-CO-18](https://docs.peppol.eu/poacc/billing/3.0/rules/ubl-tc434/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.

## Links

- [This rule as a web page](https://ironfang.uk/docs/finance/rules/BR-CO-18)
- [Free Peppol invoice validator](https://ironfang.uk/tools/peppol-validator)
- [Rule index](https://ironfang.uk/docs/finance/rules.md)
- [Ironfang Finance API docs](https://ironfang.uk/docs/finance)
- The same rule is available to MCP clients as the tool `finance.rule.get` on https://mcp.ironfang.uk/mcp
