The short answer
BR-S-09 fails when a VAT breakdown with category S carries a cbc:TaxAmount that does not agree with its cbc:TaxableAmount multiplied by its cbc:Percent. Recalculate the amount as taxable amount x rate / 100, rounded to two decimals, and update the totals that include it.
It normally arrives with BR-CO-17, which makes the same comparison on every breakdown whatever its category, so a Standard rated breakdown with a wrong amount reports both. One correction clears the pair.
What the rule checks
The rule selects cac:TaxCategory elements with cbc:ID of S and a cac:TaxScheme/cbc:ID of VAT, inside a cac:TaxSubtotal of a cac:TaxTotal directly under the document root. Breakdowns in any other category are left to BR-CO-17 and their own category rules.
It calculates taxable amount x rate / 100, rounded to two decimals, and passes when the tax amount is less than 1.00 away from that figure. A difference of exactly 1.00 fails. On 25.00 at 20%, 5.99 passes and 6.00 fails; so do 4.01 and 4.00 on the low side.
The tolerance is how the published check is written, not a statement about what is acceptable on an invoice. An amount 0.90 out validates and is still 0.90 out.
Unlike BR-CO-17, there is no branch for a missing rate. A Standard rated breakdown without cbc:Percent fails this rule, and also BR-CO-17 and BR-48, which requires the rate.
Amounts are compared as absolute values, so the sign is not examined.
| Term | Meaning | UBL element |
|---|---|---|
| BT-118 | VAT category code | cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:ID |
| BT-117 | VAT category tax amount | cac:TaxTotal/cac:TaxSubtotal/cbc:TaxAmount |
| BT-116 | VAT category taxable amount | cac:TaxTotal/cac:TaxSubtotal/cbc:TaxableAmount |
| BT-119 | VAT category rate | cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:Percent |
How an integration ends up here
Possible causes, from the shape of the rule rather than from measured usage:
- The breakdown tax amount is a sum of per-line VAT, and one Standard rated line was taxed at a different rate from the breakdown it was grouped into.
- Two Standard rates are in use and their tax was added into one breakdown while the taxable amounts were split, or the other way round.
- The rate in the breakdown comes from a tax-code table and the tax amount from a posting made under an earlier rate.
- The taxable amount was reduced by a document-level allowance after the VAT had been calculated.
- The rate is written as
0.2rather than20.
How to fix it
- Build one Standard rated breakdown for each distinct rate, so that every breakdown has a single
cbc:Percent. - For each one, calculate
cbc:TaxableAmountxcbc:Percent/ 100 in decimal arithmetic, round to two decimals, and write the result to the breakdowncbc:TaxAmount. - If that disagrees with the VAT your system posted, resolve the disagreement at source. The category stays
S; the rule is about the amount, not the classification. - Re-sum the breakdown tax amounts into
cac:TaxTotal/cbc:TaxAmount(BR-CO-14) and recalculatecbc:TaxInclusiveAmountandcbc:PayableAmount.
The recorded example has a single Standard rated breakdown.
Taxable amount 25.00, rate 20 Calculated tax: 25.00 x 20 / 100 = 5.00 Sent: 6.50, which is 1.50 away and outside the tolerance of less than 1.00 Corrected tax amount: 5.00
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 Standard rated breakdown with 6.50 of VAT on 25.00 at 20%
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="GBP">25.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="GBP">6.50</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>Fragment of the corrected invoice: the amount is 25.00 x 20 / 100
<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>Inside the breakdown only cbc:TaxAmount differs, 6.50 against 5.00. Outside this fragment the corrected invoice also has a VAT total of 5.00 instead of 6.50, and a total with VAT and amount due of 30.00 instead of 31.50, because the failing document had carried the wrong figure through its totals. The failing document also reports BR-CO-17, the category-independent form of the same check. Nothing else fires, since those totals were consistent with each other.
What the validator reported
- The failing invoice reports BR-CO-17 and BR-S-09. 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; a credit note with the same figures reports the same two rules. - Only category
Sunder theVATtax scheme is in scope. WhenBR-CO-17is reported withoutBR-S-09, look for the faulty breakdown in another category. - This rule takes the taxable amount as given. Whether that amount matches the Standard rated lines, allowances and charges is checked by
BR-S-08.
Related rules
- BR-CO-17 applies the same calculation to every VAT breakdown and adds the zero-rate and no-rate cases
- BR-S-08 checks the Standard rated taxable amount against lines, allowances and charges
- BR-CO-14 checks the VAT total against the sum of the breakdown amounts
- BR-S-01 requires the Standard rated breakdown to exist in the first place
- Browse every rule in the reference
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-S-09 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.
