The short answer
BR-04 fails when the document root has no type code with a value: no cbc:InvoiceTypeCode in an Invoice, no cbc:CreditNoteTypeCode in a CreditNote, or one that is empty. Add the element with the code for the kind of document you are sending, 380 for a commercial invoice or 381 for a credit note.
The UBL schema treats the type code as optional, so the XSD layer passes without it and this EN 16931 rule is the first to object.
What the rule checks
The rule runs once per document, on the root. It passes when either type code element directly under the root has text other than whitespace.
An absent element gives BR-04 alone, as in the recorded example, because the code list rules have no element to test. An empty or whitespace-only element gave four findings when tried: BR-04, BR-CL-01, the Peppol type code rule for that root (PEPPOL-EN16931-P0100 or PEPPOL-EN16931-P0101) and PEPPOL-EN16931-R008.
The rule does not judge the value. Any non-blank text satisfies it; whether the code is permitted is for BR-CL-01 and the Peppol profile rules to decide.
| Term | Meaning | UBL element |
|---|---|---|
| BT-3 | Invoice type code | cbc:InvoiceTypeCode (cbc:CreditNoteTypeCode in a credit note) |
How an integration ends up here
Possible causes, from the shape of the rule rather than from measured usage:
- The mapping was built for a format where the message type implies the document type, and nothing sets the UBL element.
- The type code is filled from a configuration value that is missing in this environment, and the serialiser drops the element.
- A credit note template was derived from the invoice template, and the invoice type code line was deleted without adding
cbc:CreditNoteTypeCodein its place.
How to fix it
- Decide what the document is in business terms, and choose the code from the Peppol list for that root element:
380for an ordinary invoice,381for an ordinary credit note. - Emit
cbc:InvoiceTypeCodein its schema position: aftercbc:IssueDateandcbc:DueDate, before anycbc:Note,cbc:TaxPointDateandcbc:DocumentCurrencyCode. Placed aftercbc:DocumentCurrencyCode, it failed the XSD layer when tried. - For a
CreditNote, emitcbc:CreditNoteTypeCodeinstead; the invoice element name is not valid there. - Make the code a required output of the mapping, so a missing value stops the export instead of silently dropping the element.
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 header goes from the due date straight to the currency
<cbc:IssueDate>2026-09-08</cbc:IssueDate>
<cbc:DueDate>2026-10-08</cbc:DueDate>
<!-- no cbc:InvoiceTypeCode in the failing document -->
<cbc:DocumentCurrencyCode>GBP</cbc:DocumentCurrencyCode>Fragment of the corrected invoice: 380, commercial invoice, between the due date and the currency
<cbc:IssueDate>2026-09-08</cbc:IssueDate>
<cbc:DueDate>2026-10-08</cbc:DueDate>
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
<cbc:DocumentCurrencyCode>GBP</cbc:DocumentCurrencyCode>The corrected invoice has <cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode> between the due date and the currency code; the failing invoice has no type code element at all. The failing document reports only BR-04. With no element present, neither BR-CL-01 nor PEPPOL-EN16931-P0100 has a value to check, so the Peppol layer passes.
What the validator reported
- The failing invoice reports BR-04. 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. A credit note withoutcbc:CreditNoteTypeCodereported this rule when tried, and it too passed the XSD layer. - The finding comes from the EN 16931 layer. Peppol has no presence rule of its own for the type code.
- Once the element is present, its value is checked by
BR-CL-01against the EN 16931 list and byPEPPOL-EN16931-P0100orPEPPOL-EN16931-P0101against the narrower Peppol list.
Related rules
- BR-CL-01 checks the type code value against the EN 16931 lists once it is present
- PEPPOL-EN16931-P0100 limits invoice type codes to the Peppol list
- PEPPOL-EN16931-P0101 limits credit note type codes to the Peppol list
- PEPPOL-EN16931-R008 joins this rule when the type code element is present but empty
- 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-04 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.
