The short answer
BR-S-08 fails when the cbc:TaxableAmount of a Standard rated VAT breakdown does not match what the document contains at that rate. Take the breakdown cbc:Percent, add the cbc:LineExtensionAmount of every line with category S at that rate, add the document-level charges with category S at that rate, subtract the document-level allowances with category S at that rate, and write the result as the taxable amount.
The grouping is by rate as well as by category. Lines at a different Standard rate, and lines in other categories, belong to other breakdowns.
What the rule checks
The rule runs once for each breakdown whose cac:TaxCategory has cbc:ID of S under the VAT scheme, using that breakdown's own rate. Rates are compared as numbers, so 20 in the breakdown matches 20.00 on a line.
First, something Standard rated at that rate has to exist: a line, or an allowance or charge carrying a cac:TaxCategory. A breakdown at 19% over lines at 20% fails on this point however its amounts are set.
Then the taxable amount is compared with: line net amounts, plus document-level charges, minus document-level allowances, each filtered to category S and the same rate. Only cac:AllowanceCharge elements directly under the document root enter the sum; line-level allowances and charges are already inside the line net amount.
The comparison has a tolerance. The rule passes when the taxable amount is less than 1.00 away from the calculated figure, and fails at a difference of exactly 1.00. Against a calculated 58.50, taxable amounts of 57.51 and 59.49 pass; 57.50 and 59.50 fail.
Being inside the tolerance does not make the amount correct. A taxable amount of 59.40 against a calculated 58.50 passed every validation layer when we tried it, and it is still 0.90 out. Send the calculated figure.
Two breakdowns for the same Standard rate both fail, because each one is compared with the whole sum for that rate.
| Term | Meaning | UBL element |
|---|---|---|
| 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 |
| BT-131 | Invoice line net amount | cac:InvoiceLine/cbc:LineExtensionAmount |
| BT-152 | Invoiced item VAT rate | cac:InvoiceLine/cac:Item/cac:ClassifiedTaxCategory/cbc:Percent |
| BT-99 | Document level charge amount | cac:AllowanceCharge[cbc:ChargeIndicator = true]/cbc:Amount |
| BT-92 | Document level allowance amount | cac:AllowanceCharge[cbc:ChargeIndicator = false]/cbc:Amount |
How an integration ends up here
Possible causes, from the shape of the rule rather than from measured usage:
- The taxable amount is built from the lines alone and the document-level charge or allowance is forgotten, or applied with the wrong sign.
- Lines are grouped by category but not by rate, so two Standard rates end up in one breakdown.
- Negative lines, such as corrections or returns, are skipped when summing.
- Zero rated or exempt lines are included in the Standard rated taxable amount.
- The breakdown rate comes from a different source from the line rates and the two disagree, for instance after a rate change.
- The taxable amount is derived backwards from a gross figure instead of being summed from the net amounts in the document.
How to fix it
- Collect the lines whose
cac:Item/cac:ClassifiedTaxCategoryhascbc:IDofS, and group them bycbc:Percent. - For each rate, sum the line
cbc:LineExtensionAmountvalues, add the root-levelcac:AllowanceChargeamounts withcbc:ChargeIndicatoroftruein categorySat that rate, and subtract those withfalse. Use decimal arithmetic. - Emit exactly one
cac:TaxSubtotalper rate with that figure ascbc:TaxableAmountand the rate ascbc:Percent. - Recalculate the breakdown
cbc:TaxAmountfrom the corrected taxable amount.BR-S-09andBR-CO-17check it, and the VAT total and total with VAT follow from there.
The recorded example has two Standard rated lines at 20%, one Zero rated line, and a document-level allowance and charge that are both Standard rated at 20%.
Standard rated lines at 20%: 58.00 + (-2.00) = 56.00 Document-level charge, S at 20%: + 3.50 Document-level allowance, S at 20%: - 1.00 Taxable amount for S at 20%: 56.00 + 3.50 - 1.00 = 58.50 The Zero rated line of 10.00 is not part of this figure Sent: 60.00, which is 1.50 away, so the rule fails
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: 60.00 taxable, while the Standard rated content at 20% nets to 58.50
<cac:AllowanceCharge>
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
<!-- reason code and reason omitted from this fragment -->
<cbc:Amount currencyID="GBP">1.00</cbc:Amount>
<!-- tax category S at 20 omitted from this fragment -->
</cac:AllowanceCharge>
<cac:AllowanceCharge>
<cbc:ChargeIndicator>true</cbc:ChargeIndicator>
<!-- reason code, reason, multiplier and base amount omitted from this fragment -->
<cbc:Amount currencyID="GBP">3.50</cbc:Amount>
<!-- tax category S at 20 omitted from this fragment -->
</cac:AllowanceCharge>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="GBP">60.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="GBP">11.70</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>
<!-- Standard rated lines at 20: LineExtensionAmount 58.00 and -2.00. Zero rated line: 10.00 -->Fragment of the corrected invoice: 58.00 - 2.00 + 3.50 - 1.00 = 58.50
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="GBP">58.50</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="GBP">11.70</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>Only the Standard rated cbc:TaxableAmount differs: 60.00 in the failing invoice, 58.50 in the corrected one. The document reports only BR-S-08. The tax amount of 11.70 is 0.30 away from 20% of 60.00, which is inside the tolerance of BR-CO-17 and BR-S-09, and the VAT total and monetary totals are the same in both documents.
What the validator reported
- The failing invoice reports BR-S-08. 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. In a credit note the lines arecac:CreditNoteLineand the sum is built the same way; a credit note with the same 60.00 reports the same rule. - Only Standard rated breakdowns are in scope. The other VAT categories have their own taxable amount rules.
- The rule does not look at
cac:LegalMonetaryTotal. The total without VAT is checked separately byBR-CO-13. - A Standard rated line at a rate that has no breakdown is not reported by this rule, which starts from the breakdowns that are present.
Related rules
- BR-S-09 checks the Standard rated tax amount calculated from this taxable amount
- BR-S-01 requires a Standard rated breakdown whenever Standard rated content exists
- BR-CO-13 checks the total without VAT, built from the same lines, allowances and charges
- BR-CO-10 checks the sum of the line net amounts that feed this figure
- 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-08 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.
