The short answer
BR-S-10 fails when the cac:TaxCategory of a VAT breakdown with category S contains cbc:TaxExemptionReason or cbc:TaxExemptionReasonCode. Delete them: a Standard rated breakdown is complete with its category, its rate and the VAT tax scheme.
If the reason was added because part of the invoice really is exempt or not taxed, that part needs its own category and its own breakdown, and the reason belongs there.
What the rule checks
The rule checks each cac:TaxCategory with cbc:ID of S under the VAT scheme, inside a cac:TaxSubtotal of the cac:TaxTotal at the document root. It fails if either reason element is a child of that category.
Text or code on its own is enough to fail it. When tried, a lone cbc:TaxExemptionReasonCode of VATEX-EU-132 on the Standard rated breakdown reported this rule.
What the reason says does not matter, only that the element exists. An empty cbc:TaxExemptionReason on a Standard rated breakdown was still reported here, and additionally by PEPPOL-EN16931-R008 as an empty element.
Line and allowance categories are outside this rule. When tried, a reason on a Standard rated line's cac:ClassifiedTaxCategory produced only the warning UBL-CR-601, and one on a document allowance's cac:TaxCategory only the warning UBL-CR-481; both documents stayed valid. Those elements are better left out all the same.
| Term | Meaning | UBL element |
|---|---|---|
| BT-118 | VAT category code | cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:ID |
| BT-120 | VAT exemption reason text | cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:TaxExemptionReason |
| BT-121 | VAT exemption reason code | cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:TaxExemptionReasonCode |
How an integration ends up here
Possible causes, from the shape of the rule rather than from measured usage:
- The mapping copies the tax code description, such as
Standard rate, intocbc:TaxExemptionReasonfor every breakdown instead of only for the categories that need a reason. - Every tax code in the source system has its reason field filled in, and the export writes the field whenever it is not empty.
- One breakdown template serves all categories and always emits the reason elements.
- Exempt or out-of-scope content was merged into the Standard rated breakdown, and its reason came with it.
How to fix it
- Remove
cbc:TaxExemptionReasonandcbc:TaxExemptionReasonCodefrom thecac:TaxCategoryof every breakdown whosecbc:IDisS. - Change the mapping so that reason elements are emitted only for categories that call for them, such as
EandAE, and never forSorZ. - If the reason described a real exemption, correct the lines as well: exempt items need category
Eon the line and a separateEbreakdown carrying the reason, and the Standard rated breakdown then covers only the Standard rated content.
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: reason text inside the Standard rated tax category
<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>
<cbc:TaxExemptionReason>Standard rate</cbc:TaxExemptionReason>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>Fragment of the corrected invoice: category, rate and tax scheme only
<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>The failing invoice has cbc:TaxExemptionReason with the text Standard rate in its Standard rated tax category, and the corrected invoice has no reason element there; nothing else differs. The failing document reports only BR-S-10, because its categories and amounts are otherwise consistent.
What the validator reported
- The failing invoice reports BR-S-10. 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
InvoiceandCreditNote. A credit note with the same text in its Standard rated breakdown reported this rule when tried. - Reported by the EN 16931 layer as a fatal finding at the breakdown's
cac:TaxCategory, once for each Standard rated breakdown that carries a reason. BR-Z-10applies the same ban to Zero rated breakdowns. Exempt and reverse-charge breakdowns need the opposite, a reason, underBR-E-10andBR-AE-10.
Related rules
- BR-Z-10 forbids exemption reasons on Zero rated breakdowns in the same way
- BR-E-10 requires the reason on an exempt breakdown, which is where a real exemption belongs
- PEPPOL-EN16931-R008 is also reported when the reason element is present but empty
- Browse every rule in the reference
- Background: Understanding EN 16931 validation errors
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 BR-S-10 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.
