The short answer
PEPPOL-EN16931-P0106 fails for each cac:TaxCategory that carries the exemption reason code VATEX-EU-IC while its cbc:ID is not K. The finding points at that tax category. If the supply really is an intra-community supply, change the category to K; if it is not, replace the code with the one for the real exemption, or remove it.
In the recorded example the code sits in an exempt (E) breakdown. Moving to K changes the VAT treatment of the invoice, not just its coding, and brings the intra-community requirements with it.
What the rule checks
The rule selects every cac:TaxCategory whose cbc:TaxExemptionReasonCode, upper-cased, is VATEX-EU-IC, and passes only when its cbc:ID is K. Lower case is no escape: vatex-eu-ic on an exempt breakdown was reported when tried.
Every category other than K fails. On a Standard rated breakdown, the code was reported by this rule and by BR-S-10, which forbids exemption reasons there, when tried.
Document-level allowances and charges are included, because their category is a cac:TaxCategory too; a code there was reported by this rule, with the warning UBL-CR-480, when tried. Line categories are cac:ClassifiedTaxCategory and are not read: on a line the code produced only the warning UBL-CR-600.
Sibling Peppol rules tie the other category-specific codes to their categories in the same way: PEPPOL-EN16931-P0104 for VATEX-EU-G and G, PEPPOL-EN16931-P0105 for VATEX-EU-O and O, PEPPOL-EN16931-P0107 for VATEX-EU-AE and AE, and PEPPOL-EN16931-P0108 to PEPPOL-EN16931-P0111 for the margin scheme codes VATEX-EU-D, VATEX-EU-F, VATEX-EU-I and VATEX-EU-J, which belong with E.
The rule does not check that a K breakdown meets the intra-community conditions. EN 16931 rules such as BR-IC-02, BR-IC-11 and BR-IC-12 do that.
| 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 |
How an integration ends up here
Possible causes, from the shape of the rule rather than from measured usage:
- One exemption code is configured for every zero-VAT sale to an EU customer, including sales that are exempt or outside the scope of VAT for other reasons.
- The category comes from the item tax code while the exemption code comes from the customer record, so an EU customer buying an exempt item gets
EwithVATEX-EU-IC. - Intra-community supplies are mapped to
EorZbecause no VAT is charged, while the exemption code was set correctly.
How to fix it
- Establish the real VAT treatment from your tax determination.
Kis the category for an intra-community supply; if the supply is not one, the code is what has to change. - If it is an intra-community supply, set
cbc:IDtoKon the breakdown and on every line, allowance and charge it covers, and keepVATEX-EU-IC. Then supply what categoryKneeds: when tried, switching the recorded example toKbroughtBR-IC-02(seller and buyer VAT identifiers),BR-IC-11(delivery date or invoicing period) andBR-IC-12(deliver-to country), all of which need real data. - If it is exempt for another reason, keep
Eand replace the code with the VATEX code for that basis, or remove the code and give the reason as text.BR-E-10needs one of the two. - Derive the exemption code from the same decision that sets the category, so the two cannot disagree.
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: an exempt breakdown carrying the intra-community code
<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-IC</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 breakdown stays exempt and the intra-community code is removed
<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 adds <cbc:TaxExemptionReasonCode>VATEX-EU-IC</cbc:TaxExemptionReasonCode> to its exempt breakdown; the corrected one keeps category E with the reason text alone. The failing document reports only this Peppol rule. Its EN 16931 layer passes, because VATEX-EU-IC is a valid VATEX code and the text satisfies BR-E-10. The correction shown is the not-intra-community branch: the supply stays exempt and the misleading code goes.
What the validator reported
- The failing invoice reports PEPPOL-EN16931-P0106. 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. An exempt credit note carryingVATEX-EU-ICreported this rule when tried. - Reported by the Peppol layer only. EN 16931 checks that the code is on the VATEX list, through
BR-CL-22, but not which category it is used with. - A correct
Kbreakdown still needs an exemption reason code or text of its own, underBR-IC-10.
Related rules
- BR-IC-10 requires the exemption reason on an intra-community supply breakdown, where this code belongs
- BR-CL-22 checks that an exemption reason code is on the VATEX list at all
- BR-E-10 requires a reason on an exempt breakdown once the misplaced code is removed
- BR-IC-02 requires the seller and buyer VAT identifiers when the supply really is intra-community
- 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-24.1: source checked 2026-09-24, explanation last updated 2026-09-24.
The official definition of PEPPOL-EN16931-P0106 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.
