On this page
The short answer
PEPPOL-EN16931-P0105 fails for each cac:TaxCategory that carries VATEX-EU-O while its cbc:ID is not O. The code states that the supply is not subject to VAT at all, which is what category O means; next to any other category it contradicts the treatment that category declares.
The recorded example is a reverse-charge invoice to a buyer with a German VAT identifier: category AE, reason text Reverse charge, and VATEX-EU-O as well. A cross-border service can look outside the scope from the seller side, but when the customer accounts for the VAT the treatment is the reverse charge, whose code is VATEX-EU-AE.
What the rule checks
The rule matches a cac:TaxCategory on its exemption code after upper-casing, so mixed case is no way round it: Vatex-EU-o in the reverse-charge breakdown was reported when tried. The category must then be exactly O once trimmed.
It fails whatever the other category is. When tried, VATEX-EU-O in an export breakdown, category G, was reported by this rule alone, as it was in the recorded AE breakdown.
Replacing the code settles the recorded case: with VATEX-EU-AE in place of VATEX-EU-O, the reverse-charge invoice passed every layer when tried.
Moving the category is the heavier change. When tried, relabelling the breakdown and the line of the recorded example as O cleared this rule but brought BR-O-02, because a document with an O line may carry no VAT identifiers, and BR-O-05, because an O line may carry no rate.
| Term | Meaning | UBL element |
|---|---|---|
| BT-121 | VAT exemption reason code | cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:TaxExemptionReasonCode |
| 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 |
How an integration ends up here
Possible causes, from the shape of the rule rather than from measured usage:
- Cross-border business services are set up as outside the scope in the seller system, because the place of supply is abroad, while the invoice category follows the reverse-charge rules.
- A default exemption code of
VATEX-EU-Ois written into every breakdown with no VAT. - The category is chosen from the customer type and the exemption code from the product, and the two settings were never lined up.
How to fix it
- Decide which treatment applies.
Ois for supplies outside the scope of VAT altogether; if the customer accounts for the VAT under the reverse charge, the treatment isAE. - For a reverse-charge supply, keep
AEand giveVATEX-EU-AE, reason text, or both, asBR-AE-10requires. The corrected example keeps the textReverse chargeand drops the code. - For a supply that really is not subject to VAT, change the breakdown and every line it covers to
Oand keepVATEX-EU-O. Remove the line VAT rates, whichBR-O-05forbids, and the seller and buyer VAT identifiers, whichBR-O-02forbids.
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 reverse-charge breakdown carrying the not subject to VAT code
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="GBP">25.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="GBP">0.00</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>AE</cbc:ID>
<cbc:Percent>0</cbc:Percent>
<cbc:TaxExemptionReasonCode>VATEX-EU-O</cbc:TaxExemptionReasonCode>
<cbc:TaxExemptionReason>Reverse charge</cbc:TaxExemptionReason>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>Fragment of the corrected invoice: the reverse-charge breakdown states its reason as text
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="GBP">25.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="GBP">0.00</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>AE</cbc:ID>
<cbc:Percent>0</cbc:Percent>
<cbc:TaxExemptionReason>Reverse charge</cbc:TaxExemptionReason>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>The failing invoice adds <cbc:TaxExemptionReasonCode>VATEX-EU-O</cbc:TaxExemptionReasonCode> to its reverse-charge breakdown; the corrected one keeps category AE with the text Reverse charge alone. Only this Peppol rule is reported: the text satisfies BR-AE-10, and VATEX-EU-O is a listed code for BR-CL-22.
What the validator reported
- The failing invoice reports PEPPOL-EN16931-P0105. 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. When tried, an exempt credit note withVATEX-EU-Oreported this rule. - Reported on the Peppol layer only. The EN 16931 rule for category
Obreakdowns,BR-O-10, asks for some reason there but does not look at codes placed in other categories. - The code is read in the VAT breakdown and in document-level allowances and charges. Line categories are
cac:ClassifiedTaxCategoryelements and lie outside the rule.
Related rules
- BR-O-10 requires a reason, such as VATEX-EU-O, on a breakdown that really is category O
- BR-AE-10 requires the reverse-charge reason that the corrected breakdown gives as text
- PEPPOL-EN16931-P0107 ties the reverse-charge code VATEX-EU-AE to category AE
- BR-O-02 forbids VAT identifiers on a document with a not subject to VAT line
- Browse every rule in the reference
- Background: How Peppol invoice validation actually works
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-28.1: source checked 2026-09-28, explanation last updated 2026-09-28.
The official definition of PEPPOL-EN16931-P0105 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.

