The short answer
BR-65 fails when cac:CommodityClassification/cbc:ItemClassificationCode on a line has no listID attribute. Add listID with the UNTDID 7143 code for the classification the code comes from: TST for UNSPSC, STI for the EU Common Procurement Vocabulary (CPV) or HS for the Harmonised System, for example.
Without the scheme the buyer cannot tell which classification the code belongs to. Choose listID by where the code came from, not by which value validates.
What the rule checks
The rule runs on each cbc:ItemClassificationCode under cac:CommodityClassification in an invoice or credit note line and tests only that a listID attribute exists. An item with several classifications is checked code by code: when tried, a second classification without listID was reported at cac:CommodityClassification[2] while the first passed.
The attribute value is checked by BR-CL-13, not here. When tried, listID="" passed this rule and was reported by that one.
listVersionID is a separate, optional attribute and does not replace listID. A code carrying only listVersionID still failed this rule when tried, while listID="HS" with listVersionID="2022" passed.
schemeID is not an alternative either. The classification code is a UBL code type, which has no such attribute, and when tried a schemeID in place of listID was refused at the XSD layer.
| Term | Meaning | UBL element |
|---|---|---|
| BT-158 | Item classification identifier | cac:InvoiceLine/cac:Item/cac:CommodityClassification/cbc:ItemClassificationCode (cac:CreditNoteLine/cac:Item/cac:CommodityClassification/cbc:ItemClassificationCode in a credit note) |
| BT-158 | Item classification identifier: its scheme identifier attribute | cac:InvoiceLine/cac:Item/cac:CommodityClassification/cbc:ItemClassificationCode/@listID |
| BT-158 | Item classification identifier: its scheme version attribute | cac:InvoiceLine/cac:Item/cac:CommodityClassification/cbc:ItemClassificationCode/@listVersionID |
How an integration ends up here
Possible causes, from the shape of the rule rather than from measured usage:
- Products carry a classification code in the ERP with no record of which classification it belongs to, and the mapping writes the code alone.
- The scheme is held as a name such as
UNSPSCorCPV, and the attribute is skipped for names that have no entry in the translation table. - The version of the classification is written to
listVersionIDand the scheme itself is forgotten. - A buyer asked for a classification code on the invoice and it was added as a fixed value in the template, without the attribute.
How to fix it
- Identify the classification system each code was taken from: CPV in public procurement, UNSPSC, the Harmonised System, or another.
- Look up its code in the UNTDID 7143 list published with the Peppol BIS code lists.
STIis CPV,TSTis UNSPSC andHSis the Harmonised System; the codes are upper case. - Write the code to the
listIDattribute ofcbc:ItemClassificationCode, and addlistVersionIDif the classification needs a version to be read correctly. - If you cannot establish the scheme, leave the classification out. It is optional, and a code with a guessed scheme misleads the buyer.
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 classification code has no listID
<cac:Item>
<cbc:Name>Example service</cbc:Name>
<!-- standard identifier omitted from this fragment -->
<cac:CommodityClassification>
<cbc:ItemClassificationCode>80111600</cbc:ItemClassificationCode>
</cac:CommodityClassification>
<!-- tax category and item attribute omitted from this fragment -->
</cac:Item>Fragment of the corrected invoice: listID TST identifies the code as a UNSPSC code
<cac:Item>
<cbc:Name>Example service</cbc:Name>
<!-- standard identifier omitted from this fragment -->
<cac:CommodityClassification>
<cbc:ItemClassificationCode listID="TST">80111600</cbc:ItemClassificationCode>
</cac:CommodityClassification>
<!-- tax category and item attribute omitted from this fragment -->
</cac:Item>Only the listID attribute differs: missing in the failing invoice, TST, the UNTDID 7143 code for UNSPSC, in the corrected one. The failing document reports only BR-65, since BR-CL-13 has no attribute value to look up. On a real invoice the attribute names whichever classification your own code comes from.
What the validator reported
- The failing invoice reports BR-65. 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
cac:InvoiceLinein anInvoiceandcac:CreditNoteLinein aCreditNote. When tried, a credit note whose classification code lost itslistIDreported this rule alone. - Commodity classification is optional. A line without
cac:CommodityClassificationpasses both this rule andBR-CL-13. - The classification code and the item standard identifier use different attributes and lists:
listIDwith UNTDID 7143 here,schemeIDwith the ISO 6523 ICD list oncac:StandardItemIdentification.
Related rules
- BR-CL-13 checks that the listID value is a UNTDID 7143 code
- BR-64 is the matching attribute check for the item standard identifier
- BR-CL-21 checks the scheme code of the item standard identifier against the ICD list
- 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-65 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.
