Skip to content

UBL-DT-01: Write every amount with no more than two decimals

An amount has more than two digits after the decimal point. Every amount element is limited to two, except the item net price and allowances on the price.

EN 16931Fatal: the document is invalidTotalsVAT

The short answer

UBL-DT-01 fails once for each element whose name ends in Amount and whose text has more than two characters after the decimal point. The finding location is that element; write its value with two decimals at most, for example 11.70 instead of 11.700.

Two kinds of amount are exempt: cbc:PriceAmount, and the amounts of an allowance inside cac:Price. Everything else, from line amounts to the VAT total, is held to two decimals, and most amounts also have a BR-DEC rule of their own that is reported beside this one.

What the rule checks

The rule picks elements by name, at any depth: anything whose name ends in Amount. For each, it takes the text, finds the first decimal point and fails when more than two characters follow. Trailing zeros count, and so does trailing whitespace; when tried, 11.70 followed by a space failed.

The exemptions depend on the element name and its position. The item net price is excluded wherever it appears, and so are cbc:Amount and cbc:BaseAmount inside cac:Price/cac:AllowanceCharge, which carry the price discount and the gross price. The corrected invoice in the recorded example has a net price of 19.995 and validates cleanly.

The VAT total directly under cac:TaxTotal has no working decimals rule of its own in this release: the dedicated check for it does not report, so this rule is the only finding for 11.700 there. The VAT total in an accounting currency is in the same position; when tried, 13.456 in a second tax total reported this rule alone.

Where an amount does have its own rule, the two arrive together. When tried, padding all twelve two-decimal amounts of a minimal invoice to three decimals produced twelve UBL-DT-01 findings and eleven BR-DEC findings: one each for every amount except the VAT total.

TermMeaningUBL element
-Any element whose name ends in AmountAt any depth, for example cac:LegalMonetaryTotal/cbc:PayableAmount or cac:InvoiceLine/cac:AllowanceCharge/cbc:Amount
BT-110Invoice total VAT amount (the element in the recorded example)cac:TaxTotal/cbc:TaxAmount
BT-146Item net price (exempt)cac:InvoiceLine/cac:Price/cbc:PriceAmount (cac:CreditNoteLine/cac:Price/cbc:PriceAmount in a credit note)
BT-147Item price discount (exempt)cac:InvoiceLine/cac:Price/cac:AllowanceCharge/cbc:Amount
BT-148Item gross price (exempt)cac:InvoiceLine/cac:Price/cac:AllowanceCharge/cbc:BaseAmount

How an integration ends up here

Possible causes, from the shape of the rule rather than from measured usage:

  • A number formatter is configured once, with three or four decimals to suit prices and quantities, and applied to amounts as well.
  • Amounts are computed in a type with more precision and written without rounding, so a value like 11.704 reaches the XML.
  • A decimal database column with a scale of three or more is written at full scale, turning 11.7 into 11.700.
  • A template engine writes a space or a line break inside the element along with the value.

How to fix it

  1. Use the finding location to identify each element. Every offending amount has its own finding, so the list is complete.
  2. Round the value to two decimals where it is calculated, not only where it is formatted, so the totals built on it use the same figure.
  3. Format every amount with at most two decimals and no surrounding whitespace. Keep extra decimals only on cbc:PriceAmount and on the allowance inside cac:Price, where they are allowed.
  4. If rounding changed a value, recalculate the totals that depend on it before sending.

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 VAT total is written as 11.700

<cac:TaxTotal>
  <cbc:TaxAmount currencyID="GBP">11.700</cbc:TaxAmount>
  <cac:TaxSubtotal>
    <cbc:TaxableAmount currencyID="GBP">58.50</cbc:TaxableAmount>
    <cbc:TaxAmount currencyID="GBP">11.70</cbc:TaxAmount>
    <!-- tax category omitted from this fragment -->
  </cac:TaxSubtotal>
  <!-- zero-rated breakdown omitted from this fragment -->
</cac:TaxTotal>

Fragment of the corrected invoice: the VAT total written as 11.70, like its breakdown

<cac:TaxTotal>
  <cbc:TaxAmount currencyID="GBP">11.70</cbc:TaxAmount>
  <cac:TaxSubtotal>
    <cbc:TaxableAmount currencyID="GBP">58.50</cbc:TaxableAmount>
    <cbc:TaxAmount currencyID="GBP">11.70</cbc:TaxAmount>
    <!-- tax category omitted from this fragment -->
  </cac:TaxSubtotal>
  <!-- zero-rated breakdown omitted from this fragment -->
</cac:TaxTotal>

The VAT total directly under cac:TaxTotal is written 11.700 in the failing invoice and 11.70 in the corrected one; the breakdowns and all other totals are identical, and the value itself is the same. The failing document reports only UBL-DT-01, at cac:TaxTotal/cbc:TaxAmount. The EN 16931 decimals rule meant for the VAT total does not fire in this release, and the arithmetic checks compare values, which are equal, so nothing else is reported.

What the validator reported

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 Invoice and CreditNote, and to amounts anywhere in either, including those on cac:InvoiceLine and cac:CreditNoteLine. When tried, a credit note with a VAT total of 11.700 reported this rule alone, as the invoice does.
  • It is reported by the EN 16931 layer although it checks the UBL data type rather than a business term. The XSD layer runs first and accepts 11.700 as a valid decimal, so the problem only surfaces here.
  • A value that is not a decimal at all, such as one with a comma or an empty amount element, fails the XSD layer instead, and the business rule layers are skipped.
  • An unrounded value is a different case from a padded one. When tried, 11.704 in the VAT total also brought BR-CO-14, because it is not the sum of the breakdowns; 11.700 is, and brought nothing else.

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 UBL-DT-01 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.