BR-CO-25:Payment due date or payment terms required when amount due is positive
Fix: Step 1: Read BT-115 (cbc:PayableAmount). If it's ≤ 0, the rule cannot fire — investigate why the validator reports it. Step 2: If BT-115 > 0, decide whether to emit a Payment due date or Payment terms (or both): • If your ERP has a contractual due date, write it as `<cbc:DueDate>YYYY-MM-DD</cbc:DueDate>` directly under the cbc:InvoiceTypeCode-level part of the Invoice/CreditNote root. • If the contract is net-30 / net-15 / on receipt and no fixed date applies, emit `<cac:PaymentTerms><cbc:Note>Net 30 days from invoice date</cbc:Note></cac:PaymentTerms>` with a non-empty, human-readable note. Step 3: Make sure the cbc:Note text is not empty and not pure whitespace. Some validators reject `<cbc:Note></cbc:Note>` even though the element exists. Step 4: For credit notes, prefer cac:PaymentTerms/cbc:Note over cbc:DueDate — historically more reliable across validator implementations. Step 5: Recalculate BT-115 to make sure the sign matches the document type (positive on Invoice, sign convention on CreditNote). Step 6: Re-validate. BR-CO-25 should clear without affecting other rules. Provide the required value in the free validator.
BR-CO-25 fires when the Amount due for payment (BT-115) is greater than zero but neither the Payment due date (BT-9, cbc:DueDate) nor the Payment terms (BT-20, cac:PaymentTerms/cbc:Note) is present. Peppol requires the buyer to know when to pay or under what terms — a positive amount with no payment timing is a fatal validation error.
Engine Classification
Business data required · Explicit input workflow · No assumptions made
Required input: Line IDs (comma-separated)
What is BR-CO-25?
BR-CO-25 is a fatal validation rule defined in the EN 16931 specification. It validates the >`) does not satisfy the rule on some validator implementations even though exists() returns true; the safer pattern is a non-empty literal. element under PaymentTerms > Note))) or (. <= 0)`. Common failure modes: (1) The invoice is exported without a due date because the ERP stores the due date on the payment-schedule subrecord and the UBL mapping reads only the header. (2) The invoice has cac:PaymentTerms but the only child is cac:SettlementPeriod or cac:PaymentMeans — not cbc:Note — so the schematron's exists() check fails. (3) Net-zero invoices (totals correct but cbc:PayableAmount > 0 because a prepayment was not subtracted) trip the rule unexpectedly. (4) Credit notes with a positive PayableAmount due to refund logic — historically there was a known schematron issue on credit notes where DueDate at the root is not a valid element. (5) Empty cbc:Note (`<cbc:Note in the UBL invoice XML.
When this rule fires, the invoice is rejected by Peppol access points and never reaches the buyer.
Target path: The rule's XPath is roughly `((. > 0) and (exists(//cbc:DueDate) or exists(//cac:PaymentTerms/cbc:Note))) or (. <= 0)`. Common failure modes: (1) The invoice is exported without a due date because the ERP stores the due date on the payment-schedule subrecord and the UBL mapping reads only the header. (2) The invoice has cac:PaymentTerms but the only child is cac:SettlementPeriod or cac:PaymentMeans — not cbc:Note — so the schematron's exists() check fails. (3) Net-zero invoices (totals correct but cbc:PayableAmount > 0 because a prepayment was not subtracted) trip the rule unexpectedly. (4) Credit notes with a positive PayableAmount due to refund logic — historically there was a known schematron issue on credit notes where DueDate at the root is not a valid element. (5) Empty cbc:Note (`<cbc:Note/>`) does not satisfy the rule on some validator implementations even though exists() returns true; the safer pattern is a non-empty literal.
Why This Error Matters
Invoice rejected. Buyers need to know when payment is expected.
BR-CO-25 is a hard failure — the invoice must be corrected and re-sent before it can reach the recipient.
Validator Behavior
- ·Causes invoice rejection
- ·Error returned: BR-CO-25
- ·Specification: EN 16931
How to Fix It
Check all line IDs
Review InvoiceLine/ID values
Make unique
Use sequential numbers or unique identifiers
Before / After
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
<cbc:ID>INV-2026-0042</cbc:ID>
<cbc:IssueDate>2026-05-26</cbc:IssueDate>
<!-- no cbc:DueDate, no cac:PaymentTerms -->
<cac:LegalMonetaryTotal>
<cbc:PayableAmount currencyID="EUR">1190.00</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
</Invoice><Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
<cbc:ID>INV-2026-0042</cbc:ID>
<cbc:IssueDate>2026-05-26</cbc:IssueDate>
<cbc:DueDate>2026-06-25</cbc:DueDate>
<cac:PaymentTerms>
<cbc:Note>Net 30 days from invoice date</cbc:Note>
</cac:PaymentTerms>
<cac:LegalMonetaryTotal>
<cbc:PayableAmount currencyID="EUR">1190.00</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
</Invoice>Technical Reference
The rule's XPath is roughly `((. > 0) and (exists(//cbc:DueDate) or exists(//cac:PaymentTerms/cbc:Note))) or (. <= 0)`. Common failure modes: (1) The invoice is exported without a due date because the ERP stores the due date on the payment-schedule subrecord and the UBL mapping reads only the header. (2) The invoice has cac:PaymentTerms but the only child is cac:SettlementPeriod or cac:PaymentMeans — not cbc:Note — so the schematron's exists() check fails. (3) Net-zero invoices (totals correct but cbc:PayableAmount > 0 because a prepayment was not subtracted) trip the rule unexpectedly. (4) Credit notes with a positive PayableAmount due to refund logic — historically there was a known schematron issue on credit notes where DueDate at the root is not a valid element. (5) Empty cbc:Note (`<cbc:Note/>`) does not satisfy the rule on some validator implementations even though exists() returns true; the safer pattern is a non-empty literal.Code Example
The 'before' invoice has a positive PayableAmount but no DueDate and no PaymentTerms/Note — fatal under BR-CO-25. The 'after' adds both cbc:DueDate (BT-9) and cac:PaymentTerms/cbc:Note (BT-20). Either one alone satisfies the rule; including both is the most defensive option and improves human readability for the buyer's accounts payable team.Common Causes
- ·The rule's XPath is roughly `((. > 0) and (exists(//cbc:DueDate) or exists(//cac:PaymentTerms/cbc:Note))) or (. <= 0)`. Common failure modes: (1) The invoice is exported without a due date because the ERP stores the due date on the payment-schedule subrecord and the UBL mapping reads only the header. (2) The invoice has cac:PaymentTerms but the only child is cac:SettlementPeriod or cac:PaymentMeans — not cbc:Note — so the schematron's exists() check fails. (3) Net-zero invoices (totals correct but cbc:PayableAmount > 0 because a prepayment was not subtracted) trip the rule unexpectedly. (4) Credit notes with a positive PayableAmount due to refund logic — historically there was a known schematron issue on credit notes where DueDate at the root is not a valid element. (5) Empty cbc:Note (`<cbc:Note/>`) does not satisfy the rule on some validator implementations even though exists() returns true; the safer pattern is a non-empty literal.
Seeing this in production? The API handles BR-CO-25 automatically. See the fix response →
Frequently Asked Questions
Your invoice has a positive amount due for payment (BT-115) but no payment due date (cbc:DueDate) and no payment terms note (cac:PaymentTerms/cbc:Note). Peppol requires at least one so the buyer knows when or under what conditions to pay.
Partially. We can detect the missing element and inject a default cac:PaymentTerms/cbc:Note ('Payment due on receipt' or your configured default), but a real due date requires input from the source system. Confidence is 0.55 — auto-fix is safe for fallback text, manual review is recommended for the actual date.
Technically the schematron exists() check passes on any present element, including empty ones, but several validator implementations (notably the KoSIT and OpenPeppol reference validators) also enforce non-empty content. Always emit non-empty, human-readable text.
There has been a known issue (eInvoicing-EN16931 GitHub #84) where the schematron looks for cbc:DueDate at the document root on credit notes even though the UBL CreditNote schema places it elsewhere. The reliable workaround is to emit cac:PaymentTerms/cbc:Note on credit notes with a positive PayableAmount instead of relying on cbc:DueDate.
Related Errors
Related Content
Last updated: 5 June 2026
Validate your invoice
Drop your XML here to check for BR-CO-25
Fix BR-CO-25 with guided input
Upload your invoice and we'll ask for the missing data, then apply a safe, auditable fix.