A rejected Peppol invoice fails in one of two layers, and the error code tells you which. XSD errors mean the XML structure itself is wrong – an element missing, misplaced or mistyped against the UBL schema. Schematron errors mean the XML is well-formed but the content breaks a business rule; these carry the code families everyone pastes into AI assistants: `BR-` rules come from the European standard EN 16931, while `PEPPOL-EN16931-R` rules are the network’s own additions. Read the family before the message and you already know whose rulebook you violated – the standard’s or the network’s.
What do the code families mean?
| Code family | Layer | What it checks |
|---|---|---|
| (parser error) | XSD | UBL structure: element names, order, data types |
| BR- | Schematron / EN 16931 | Core business rules: mandatory terms present |
| BR-CO- | Schematron / EN 16931 | Calculations and conditions: totals must agree |
| BR-S/E/AE/K/G/O- | Schematron / EN 16931 | VAT category rules per rate type |
| PEPPOL-EN16931-R | Schematron / Peppol | Network rules layered on the standard |
| -CL | Schematron | Code-list checks: currency, country, scheme codes |
Rules also carry severity: a fatal error blocks the document, a warning does not – worth checking before you spend an afternoon on something the network would have accepted anyway.
Why do totals fail so often?
The calculation rules (the `BR-CO-*` family) cross-check the document’s arithmetic: line net amounts must sum to the tax-exclusive total, VAT category amounts must match their bases and rates, and the payable amount must close the chain. The classic cause is rounding: your application rounds per line, the rule checks the sum, and a cent of drift rejects the invoice. The reliable fix is to compute the UBL totals from the same rounded values you print on the lines, not from the unrounded database figures.
How to debug a rejected invoice, in order
Fix XSD errors first – until the structure parses, Schematron results are noise. Then fix the first Schematron error and revalidate: later errors frequently cascade from the first (one missing VAT category line can trip half a dozen dependent rules). Check the rule’s severity before treating it as a blocker. And if you validate through an Access Point API that checks synchronously before accepting, wire those structured reports into your test suite – validation failures then surface in CI, not in production. For the standards map behind these layers, see how to generate a valid UBL invoice.
What is the difference between XSD and Schematron errors in Peppol?
XSD errors mean broken XML structure against the UBL schema; Schematron errors mean well-formed XML whose content violates business rules (BR-* from EN 16931, PEPPOL-* from the network).
What are BR-CO errors?
EN 16931 calculation and condition rules — they cross-check totals: line sums, VAT category amounts and the payable amount must agree arithmetically. Rounding drift is the classic cause.
Are all Peppol validation errors blocking?
No. Rules carry severity — fatal errors block the document, warnings do not. Check severity before treating every message as a defect.
In what order should I debug a rejected Peppol invoice?
XSD structure first, then the first Schematron error (later ones often cascade), checking rule severity as you go. Synchronous API validation lets your CI catch these.