On this page
The short answer
BR-CO-20 fails when a cac:InvoicePeriod inside a line contains neither cbc:StartDate nor cbc:EndDate. Put the service dates of that line in it, or drop the element from lines that do not bill for a period.
The recorded example is the empty <cac:InvoicePeriod/> a template writes when both dates are null. Peppol rejects that element for being empty as well, under PEPPOL-EN16931-R008.
What the rule checks
The rule visits each line cac:InvoicePeriod, in cac:InvoiceLine or cac:CreditNoteLine, and passes when at least one of the two date elements is there. A start date alone or an end date alone is enough; when tried, each passed every layer.
Nothing else in a line period counts. When tried, a line period holding only cbc:DescriptionCode 35 reported BR-CO-20 with the warning UBL-CR-523, and one holding only a cbc:Description reported it with UBL-CR-524.
The line rule is stricter than the one for the whole document. When tried, a period holding only cbc:DescriptionCode 35 passed at document level, where BR-CO-19 accepts the code as a VAT point date code.
Whitespace does not make the element any less empty. When tried, an opening and a closing cac:InvoicePeriod tag on separate lines, with only whitespace between them, reported the same two rules as the recorded example.
Blank date elements never reach this rule: an empty cbc:StartDate or cbc:EndDate is not a valid date in the UBL schema, and when tried the XSD layer failed before any business rule ran.
| Term | Meaning | UBL element |
|---|---|---|
| BG-26 | Invoice line period | cac:InvoiceLine/cac:InvoicePeriod (cac:CreditNoteLine/cac:InvoicePeriod in a credit note) |
| BT-134 | Invoice line period start date | cac:InvoiceLine/cac:InvoicePeriod/cbc:StartDate (cac:CreditNoteLine/cac:InvoicePeriod/cbc:StartDate in a credit note) |
| BT-135 | Invoice line period end date | cac:InvoiceLine/cac:InvoicePeriod/cbc:EndDate (cac:CreditNoteLine/cac:InvoicePeriod/cbc:EndDate in a credit note) |
How an integration ends up here
Possible causes, from the shape of the rule rather than from measured usage:
- The line template always writes
cac:InvoicePeriodand fills the dates only for subscription or usage lines, so one-off items get an empty period. - The serialiser drops null date fields but keeps their parent element.
- A billing period label such as a month name is written to
cbc:Descriptionon the line instead of being turned into dates. - The mapping for the document period, which may carry a VAT point date code, was reused for lines, where the code has no place.
How to fix it
- Find the line in the finding location, for example
cac:InvoiceLine[1]/cac:InvoicePeriod[1]. - If the line bills a service period, write its first day to
cbc:StartDateand its last day tocbc:EndDateasYYYY-MM-DD, or at least the one date the source holds. - If the line is not tied to a period, remove
cac:InvoicePeriodfrom it. The group is optional on a line. - Emit the element only when one of its dates has a value, so that a null can never produce an empty group again.
- Keep period labels out of the line:
cbc:Descriptionandcbc:DescriptionCodeare outside the model there and draw warnings.
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: line 1 has an empty period element
<cac:InvoiceLine>
<cbc:ID>1</cbc:ID>
<cbc:InvoicedQuantity unitCode="C62">2</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="GBP">25.00</cbc:LineExtensionAmount>
<cac:InvoicePeriod/>
<!-- item and price omitted from this fragment -->
</cac:InvoiceLine>Fragment of the corrected invoice: the line period runs from 1 to 15 August
<cac:InvoiceLine>
<cbc:ID>1</cbc:ID>
<cbc:InvoicedQuantity unitCode="C62">2</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="GBP">25.00</cbc:LineExtensionAmount>
<cac:InvoicePeriod>
<cbc:StartDate>2026-08-01</cbc:StartDate>
<cbc:EndDate>2026-08-15</cbc:EndDate>
</cac:InvoicePeriod>
<!-- item and price omitted from this fragment -->
</cac:InvoiceLine>The failing invoice has an empty <cac:InvoicePeriod/> on line 1 where the corrected one has a start date of 2026-08-01 and an end date of 2026-08-15; the document period for August is the same in both. Beside BR-CO-20, the failing document reports PEPPOL-EN16931-R008 at the same element, because an element with no content is not allowed. Filling in the dates, or removing the element, clears both.
What the validator reported
- The failing invoice reports BR-CO-20 and PEPPOL-EN16931-R008. 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
InvoiceandCreditNote. When tried, an empty period on acac:CreditNoteLinereportedBR-CO-20andPEPPOL-EN16931-R008in the same way. - The period of the whole document is a matter for
BR-CO-19: when tried, an emptycac:InvoicePeriodunder the root reported that rule, not this one. - Once both dates are present,
BR-30checks their order, and against a document periodPEPPOL-EN16931-R110andPEPPOL-EN16931-R111check that the line stays inside it.
Related rules
- BR-CO-19 is the date requirement for the invoicing period of the whole document
- BR-30 checks that a line period with both dates does not end before it starts
- PEPPOL-EN16931-R008 rejects the empty line period of the recorded example
- PEPPOL-EN16931-R110 compares each line start date with the start of the invoicing period
- 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-28.1: source checked 2026-09-28, explanation last updated 2026-09-28.
The official definition of BR-CO-20 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.

