Skip to content

BR-CL-22: Use a VATEX code for the VAT exemption reason code

cbc:TaxExemptionReasonCode must hold a code from the VATEX list, such as VATEX-EU-132. Made-up codes are rejected; send reason text if no code fits.

EN 16931Fatal: the document is invalidVATCode lists

The short answer

BR-CL-22 fails when a cbc:TaxExemptionReasonCode holds a value that is not in the VATEX code list, and the finding points at that element. Replace the value with the VATEX code for the actual legal basis of the exemption, or remove the code and state the reason in cbc:TaxExemptionReason if no code fits.

The recorded example uses VATEX-EU-EXEMPT, which follows the pattern of real codes but does not exist.

What the rule checks

The rule runs on every cbc:TaxExemptionReasonCode in the document and looks its value up in the VATEX list the validator carries: the EU article codes such as VATEX-EU-132 and VATEX-EU-143-1A, the category codes VATEX-EU-AE, VATEX-EU-IC, VATEX-EU-G and VATEX-EU-O, the margin scheme codes VATEX-EU-D, VATEX-EU-F, VATEX-EU-I and VATEX-EU-J, and a set of French VATEX-FR- codes.

The value is trimmed and upper-cased before the lookup, so vatex-eu-132 passed when tried. A space inside the value or a missing prefix fails: VATEX EU 132 and 132 were both rejected.

An empty element fails this rule, and when tried it also brought PEPPOL-EN16931-R008.

A code that fails here still counts as an exemption reason for BR-E-10. When tried, VATEX-EU-EXEMPT on its own, with no reason text, reported this rule and nothing else.

Only list membership is checked. Whether a listed code suits the category is a Peppol matter, handled by PEPPOL-EN16931-P0106 and its sibling rules.

TermMeaningUBL element
BT-121VAT exemption reason codecac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:TaxExemptionReasonCode
BT-120VAT exemption reason textcac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:TaxExemptionReason

How an integration ends up here

Possible causes, from the shape of the rule rather than from measured usage:

  • The code is assembled from a pattern, VATEX-EU- plus a label, instead of being chosen from the list.
  • An internal exemption code or a national legal reference is written in the code element, where only VATEX codes are accepted.
  • The article number is written without the VATEX-EU- prefix.

How to fix it

  1. Find the legal basis for the exemption in your tax determination.
  2. Look up the VATEX code for that basis, for example VATEX-EU-132 for an exemption under Article 132 of the VAT Directive, and write it exactly as listed.
  3. If no code matches, drop cbc:TaxExemptionReasonCode and state the basis in cbc:TaxExemptionReason. An exempt breakdown needs one or the other under BR-E-10.
  4. When both are sent, put the code before the text. When tried, the code after the text failed the XSD layer.

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 exempt breakdown carries an exemption code that is not in the VATEX list

<cac:TaxSubtotal>
  <cbc:TaxableAmount currencyID="GBP">25.00</cbc:TaxableAmount>
  <cbc:TaxAmount currencyID="GBP">0.00</cbc:TaxAmount>
  <cac:TaxCategory>
    <cbc:ID>E</cbc:ID>
    <cbc:Percent>0</cbc:Percent>
    <cbc:TaxExemptionReasonCode>VATEX-EU-EXEMPT</cbc:TaxExemptionReasonCode>
    <cbc:TaxExemptionReason>Exempt from VAT</cbc:TaxExemptionReason>
    <cac:TaxScheme>
      <cbc:ID>VAT</cbc:ID>
    </cac:TaxScheme>
  </cac:TaxCategory>
</cac:TaxSubtotal>

Fragment of the corrected invoice: the invalid code is gone and the reason text remains

<cac:TaxSubtotal>
  <cbc:TaxableAmount currencyID="GBP">25.00</cbc:TaxableAmount>
  <cbc:TaxAmount currencyID="GBP">0.00</cbc:TaxAmount>
  <cac:TaxCategory>
    <cbc:ID>E</cbc:ID>
    <cbc:Percent>0</cbc:Percent>
    <cbc:TaxExemptionReason>Exempt from VAT</cbc:TaxExemptionReason>
    <cac:TaxScheme>
      <cbc:ID>VAT</cbc:ID>
    </cac:TaxScheme>
  </cac:TaxCategory>
</cac:TaxSubtotal>

The failing invoice has <cbc:TaxExemptionReasonCode>VATEX-EU-EXEMPT</cbc:TaxExemptionReasonCode> before its reason text; the corrected one has the text alone. The failing document reports only BR-CL-22: the text keeps BR-E-10 satisfied, and no other rule reads an unknown code. The correction shown removes the code, but a real VATEX code in the same place, such as VATEX-EU-132, also passed every layer when tried. The text Exempt from VAT is generic example wording; a real invoice should name the actual basis.

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. An exempt credit note with VATEX-EU-EXEMPT reported this rule alone when tried.
  • Reported by the EN 16931 layer. The Peppol layer then checks that the category-specific codes are used with their categories.
  • Standard rated and Zero rated breakdowns may not carry an exemption reason at all, valid or not; BR-S-10 and BR-Z-10 reject one there.

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-CL-22 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.