The short answer
BR-28 fails when cac:Price/cac:AllowanceCharge/cbc:BaseAmount on a line is below zero. That element is the item gross price, the unit price before the price discount, and it cannot be negative. Correct the sign at source so that the gross price is positive and the net price in cbc:PriceAmount equals it minus the discount.
In the recorded example the negative gross price no longer agrees with the net price either, so PEPPOL-EN16931-R046 comes with it.
What the rule checks
For each cac:InvoiceLine or cac:CreditNoteLine, the rule reads the cbc:BaseAmount of the cac:AllowanceCharge inside cac:Price, if there is one, and requires it to be zero or more.
With no price-level cac:AllowanceCharge, or none with a cbc:BaseAmount, no gross price is stated and the rule passes. When tried, deleting the gross price from the recorded line left a valid invoice.
Zero is accepted by this rule. When tried, a gross price of 0 was not reported by BR-28; only PEPPOL-EN16931-R046 objected, because 0 minus 2.5 is not the net price of 12.5.
The sign test stands on its own. With a gross price of -15 and a discount of -27.5, which keeps the net price at 12.5, BR-28 was still reported when tried, and nothing else was.
The discount amount, the net price and the quantity are not read. A negative net price is a separate rule, BR-27.
| Term | Meaning | UBL element |
|---|---|---|
| BT-148 | Item gross price | cac:InvoiceLine/cac:Price/cac:AllowanceCharge/cbc:BaseAmount (cac:CreditNoteLine in a credit note) |
| BT-147 | Item price discount | cac:InvoiceLine/cac:Price/cac:AllowanceCharge/cbc:Amount |
| BT-146 | Item net price | cac:InvoiceLine/cac:Price/cbc:PriceAmount |
How an integration ends up here
Possible causes, from the shape of the rule rather than from measured usage:
- A credit or return line is built by negating every price field, the gross price included.
- The sign of the line net amount is copied onto the unit prices when a return is mapped.
- The gross price is derived from the net price and the discount with the operands the wrong way round, such as discount minus net price.
- A price-level entry is used to carry a credit that belongs on the line or the document.
How to fix it
- Find the line from the finding location and read
cbc:PriceAmount, and thecbc:Amountandcbc:BaseAmountinsidecac:Price/cac:AllowanceCharge. - Write the gross price as the positive unit price before discount. If the line is a credit or correction, express that through a negative
cbc:InvoicedQuantity(orcbc:CreditedQuantity) and line net amount, not through the prices. - Make sure net price = gross price - discount holds exactly, since
PEPPOL-EN16931-R046tests it with no tolerance. - If the source has no reliable gross price, leave out the whole price-level
cac:AllowanceChargeand send the net price alone.
The recorded line has a net price of 12.5 and a price discount of 2.5.
Failing: gross price -15 - discount 2.5 = -17.5, net price sent 12.5, so BR-28 and PEPPOL-EN16931-R046 both fail Corrected: gross price 15 - discount 2.5 = 12.5, which is the net price sent
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 gross price is -15
<cac:Price>
<cbc:PriceAmount currencyID="GBP">12.5</cbc:PriceAmount>
<cbc:BaseQuantity unitCode="C62">1</cbc:BaseQuantity>
<cac:AllowanceCharge>
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
<cbc:Amount currencyID="GBP">2.5</cbc:Amount>
<cbc:BaseAmount currencyID="GBP">-15</cbc:BaseAmount>
</cac:AllowanceCharge>
</cac:Price>Fragment of the corrected invoice: the gross price is 15, and 15 minus 2.5 is the net price
<cac:Price>
<cbc:PriceAmount currencyID="GBP">12.5</cbc:PriceAmount>
<cbc:BaseQuantity unitCode="C62">1</cbc:BaseQuantity>
<cac:AllowanceCharge>
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
<cbc:Amount currencyID="GBP">2.5</cbc:Amount>
<cbc:BaseAmount currencyID="GBP">15</cbc:BaseAmount>
</cac:AllowanceCharge>
</cac:Price>The gross price in cbc:BaseAmount is -15 in the failing invoice and 15 in the corrected one; nothing else changes. The failing document also reports PEPPOL-EN16931-R046 on the price discount, because -15 minus 2.5 is -17.5 while the net price is 12.5. With the sign corrected, 15 minus 2.5 gives 12.5 and both findings clear.
What the validator reported
- The failing invoice reports BR-28 and PEPPOL-EN16931-R046. 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
cac:InvoiceLineandcac:CreditNoteLine. A credit note line with the same gross price of -15 reportedBR-28andPEPPOL-EN16931-R046when tried. - Reported by the EN 16931 layer; the companion finding,
PEPPOL-EN16931-R046, comes from the Peppol layer. - The gross price feeds no total. The line net amount is worked out from the net price, so the negative figure disturbed nothing beyond the price itself.
Related rules
- BR-27 is the matching rule for a negative net price
- PEPPOL-EN16931-R046 checks the net price against this gross price and the discount
- PEPPOL-EN16931-R044 requires the same price-level element to be a discount
- 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-28 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.
