The short answer
PEPPOL-EN16931-R120 fails when a line cbc:LineExtensionAmount is more than 0.02 away from quantity x (net price / price base quantity) + line charges - line allowances. Recalculate the line from the values in the XML, find the one that disagrees with the source transaction, and correct it.
Mistakes that produce this include a quantity or price that changed without the line amount being recalculated, a price given per 100 or per 1000 without the matching cbc:BaseQuantity, and a line discount that is both netted into the price and sent as a line allowance.
What the rule checks
The rule runs once for every cac:InvoiceLine or cac:CreditNoteLine. The expected value is quantity x (cbc:PriceAmount / cbc:BaseQuantity), plus the sum of cbc:Amount over the line cac:AllowanceCharge elements with cbc:ChargeIndicator of true, minus the same sum for those with false.
The line net amount passes when it is within 0.02 of that value. The limit is inclusive. With a quantity of 2 and a line amount of 25.00, the validator accepts a price of 12.51 (expected 25.02) and 12.49, and rejects 12.511 (expected 25.022), 12.489 and 12.515.
Rounding is applied only to the two sums: the charges are added up and rounded to two decimals, and so are the allowances. Quantity x price is not rounded, and neither is the final expected value, which is why 25.022 above counts as 0.022 out. Since line allowance and charge amounts may not have more than two decimals anyway, the rounding of the sums changes nothing in a document that passes the EN 16931 decimal rules.
The price base quantity divides the price. A price of 125 with a base quantity of 10 and a quantity of 2 gives 25.00 and passes; a price of 12.5 with a base quantity of 10 gives 2.50 and fails. A missing cbc:BaseQuantity is read as 1, and so is a base quantity of 0, which PEPPOL-EN16931-R121 reports separately.
The discount inside cac:Price is not part of the formula. The net price is already after that discount, so only cbc:PriceAmount is used.
The pinned test also has fallbacks for other missing elements: a missing quantity is read as 1, a missing price as 0 and a missing line net amount as 0. Removing the quantity from the recorded line reports BR-22 and BR-23 alongside this rule, because 1 x 12.5 is not 25.00.
| Term | Meaning | UBL element |
|---|---|---|
| BT-131 | Invoice line net amount | cac:InvoiceLine/cbc:LineExtensionAmount |
| BT-129 | Invoiced quantity | cac:InvoiceLine/cbc:InvoicedQuantity |
| BT-146 | Item net price | cac:InvoiceLine/cac:Price/cbc:PriceAmount |
| BT-149 | Item price base quantity | cac:InvoiceLine/cac:Price/cbc:BaseQuantity |
| BT-136 | Invoice line allowance amount | cac:InvoiceLine/cac:AllowanceCharge[cbc:ChargeIndicator = false]/cbc:Amount |
| BT-141 | Invoice line charge amount | cac:InvoiceLine/cac:AllowanceCharge[cbc:ChargeIndicator = true]/cbc:Amount |
How an integration ends up here
Possible causes, from the shape of the rule rather than from measured usage:
- The quantity or price was edited after the line amount was stored, and the stored amount is sent as it was.
- The unit price is per 100 or per 1000 units in the source system, and the XML carries it with no
cbc:BaseQuantityor with a base quantity of 1. - A line discount is already reflected in the net price and is also sent as a line-level
cac:AllowanceCharge, so it is subtracted twice in the expected value. - The line amount is calculated from a price with more decimals than the price that is serialised, and over a large quantity the gap exceeds 0.02.
- The line amount includes VAT, or a line charge is left out of it, or a line allowance is emitted with
cbc:ChargeIndicatoroftrueso that it is added instead of subtracted.
How to fix it
- Recompute the failing line from its own XML: quantity x (
cbc:PriceAmount/cbc:BaseQuantity) + line charges - line allowances, in decimal arithmetic. - Compare each input with the source transaction to find the wrong one. Do not simply overwrite the line amount with the formula result unless the line amount really is the value that is wrong.
- If the price is per several units, send the number of units in
cbc:BaseQuantity. If it is per single unit, send 1 or leave the element out. AunitCodeon the base quantity that differs from the one on the quantity is reported asPEPPOL-EN16931-R130. - Serialise the net price with as many decimals as the calculation used. The price is not held to two decimals by this rule, and a price cut to two decimals can drift past 0.02 once it is multiplied by a large quantity.
- If the line net amount changes, recalculate the sum of line net amounts, the VAT breakdown and the document totals.
BR-CO-10checks the first of those next.
The recorded invoice line has a net price of 12.5 per 1 unit, no line allowances or charges, and a line net amount of 25.00. The third line shows a line from the fuller valid fixture with one line charge and one line allowance.
Failing: 3 x (12.5 / 1) + 0.00 - 0.00 = 37.50, line net amount 25.00, difference 12.50 Corrected: 2 x (12.5 / 1) + 0.00 - 0.00 = 25.00, line net amount 25.00, difference 0.00 With charge and allowance: 3 x (19.995 / 1) + 0.01 - 2.00 = 57.995, line net amount 58.00, difference 0.005, passes
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: 3 units at 12.5 is 37.50, but the line net amount is 25.00
<cac:InvoiceLine>
<cbc:ID>1</cbc:ID>
<cbc:InvoicedQuantity unitCode="C62">3</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="GBP">25.00</cbc:LineExtensionAmount>
<!-- item omitted from this fragment -->
<cac:Price>
<cbc:PriceAmount currencyID="GBP">12.5</cbc:PriceAmount>
<cbc:BaseQuantity unitCode="C62">1</cbc:BaseQuantity>
</cac:Price>
</cac:InvoiceLine>Fragment of the corrected invoice: 2 units at 12.5 is 25.00
<cac:InvoiceLine>
<cbc:ID>1</cbc:ID>
<cbc:InvoicedQuantity unitCode="C62">2</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="GBP">25.00</cbc:LineExtensionAmount>
<!-- item omitted from this fragment -->
<cac:Price>
<cbc:PriceAmount currencyID="GBP">12.5</cbc:PriceAmount>
<cbc:BaseQuantity unitCode="C62">1</cbc:BaseQuantity>
</cac:Price>
</cac:InvoiceLine>Only cbc:InvoicedQuantity differs: 3 in the failing document, 2 in the corrected one. The failing document reports only PEPPOL-EN16931-R120, because the line net amount of 25.00 still agrees with the document totals. In this example the quantity was the wrong value; had the line amount been changed to 37.50 instead, every total that depends on it would have needed recalculating too.
What the validator reported
- The failing invoice reports PEPPOL-EN16931-R120. The corrected document passes every layer with no findings.Download the failing XMLDownload the corrected XML
- The failing credit note reports PEPPOL-EN16931-R120. 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. On a credit note the quantity iscbc:CreditedQuantityand the line iscac:CreditNoteLine; everything else in the formula is the same. The recorded credit note example makes the same mistake, a credited quantity of 3 against a line net amount of 25.00 at a price of 12.5, and reports only this rule. The 0.02 limit was confirmed on a credit note as well. - Each line is checked on its own, in the document currency. The rule does not look at VAT or at the document totals.
- A negative
cbc:BaseQuantitymakes the unit price negative in this calculation, so on the recorded line a base quantity of -1 reports this rule together withPEPPOL-EN16931-R121. - The 0.02 allowance is per line and applies to this comparison only. It does not carry over to
BR-CO-10, which compares the document line total with the sum of the line net amounts rounded to two decimals, with no tolerance.
Related rules
- PEPPOL-EN16931-R121 rejects a price base quantity of zero or less
- PEPPOL-EN16931-R046 checks the net price against the gross price and price discount
- BR-CO-10 checks that the line net amounts add up to the document line total
- BR-DEC-23 limits the line net amount to two decimals
- Browse every rule in the reference
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-20.1: source checked 2026-09-20, explanation last updated 2026-09-20.
The official definition of PEPPOL-EN16931-R120 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.
