BR-KSA-DEC-01Allowance percentage is below zero or above one hundred

Mutabiq checks Saudi ZATCA Phase 2 e-invoice XML before you submit it: pre-validation against published ZATCA requirements, not an approval by the authority. This page explains one rule, BR-KSA-DEC-01.

Validate 5 invoices free

Five checks a month on the Free plan. The file is checked in memory and is never stored.

The message ZATCA prints

[BR-KSA-DEC-01]-The allowance percentage values (BT-94, BT-138) must be from 0.00 to 100.00, with maximum two decimal places. Only numerals are accepted, the percentage symbol (%) is not allowed.

What Mutabiq reports

One entry for each way this rule can be reported.

Reported as
What kind of value was found — empty, not_15_digits and the like — never the value itself.

Allowance percentage is below zero or above one hundred

Reported aspercentage_out_of_rangebelow zero or above one hundred

What is wrong

A cbc:MultiplierFactorNumeric - the percentage figure on a discount or a charge, BT-94 at document level and BT-138 on a line - holds a value outside the range from zero to one hundred, both ends included, and ZATCA refuses the document under its rule BR-KSA-DEC-01. The rule reads every cbc:MultiplierFactorNumeric whose parent is a cac:AllowanceCharge block, wherever that block sits: on the document, on a line, and at the price level too. It puts no condition on cbc:ChargeIndicator, so a charge's percentage is judged exactly as a discount's is. An empty element is ignored outright, because the rule's own expression requires the element to have some text in it before it looks at the value at all, so an allowance that writes cbc:MultiplierFactorNumeric with nothing inside draws nothing here. One case this range test cannot catch is worth knowing about, because it is the common one: a percentage written as a fraction - 0.15 where fifteen per cent was meant - sits inside the range and passes this rule while being wrong everywhere else it is used, and it will surface instead as a discount amount that does not match its base and percentage.

What to check in your ERP

A value outside nought to one hundred is a units problem rather than a tax one. A negative percentage usually comes from a credit note where the sign was applied to the percentage instead of to the amounts: on a credit note the amounts carry the direction and the percentage stays positive. A value above one hundred usually means the field is holding something that is not a percentage at all - an amount, a quantity or a multiplier - written there by a mapping that is one column out. Then check the units in both directions, because the range test will not do it for you: your discount table may hold 0.15 while the export template multiplies by a hundred, or it may hold 15 while the template does not, and either mismatch produces a discount that is wrong by a factor of a hundred. The reliable test is to confirm that the percentage applied to cbc:BaseAmount actually produces the cbc:Amount you wrote.

Allowance percentage is written with more than six decimal places

Reported astoo_many_decimalsmore decimal places than allowed

What is wrong

A cbc:MultiplierFactorNumeric - the percentage on a discount or a charge, BT-94 at document level and BT-138 on a line - is written with more than six characters after its first full stop, and ZATCA refuses the document under its rule BR-KSA-DEC-01. Six, not two, and that is the part to read twice: every other decimal ceiling this checker applies is two places, and this percentage is the only value in either published rule file that is allowed six. A percentage with three or four decimals is perfectly acceptable here and would fail almost anywhere else in the document. The rule counts the characters as they are written rather than judging the value, so a seventh digit fails even when it is a nought. Whitespace counts towards it: the range half of the same rule reads the value with surrounding spaces stripped away, while this half counts the raw text, so a value padded inside its element can pass the range test and fail this one. An empty element is ignored outright, because the rule requires the element to have some text in it before it looks at it at all. The rule reads every cbc:MultiplierFactorNumeric whose parent is a cac:AllowanceCharge block, wherever that block sits, and puts no condition on cbc:ChargeIndicator, so a charge's percentage is judged as a discount's is.

What to check in your ERP

Six decimals is generous enough that a percentage exceeding it is almost never a rate somebody typed - it is a rate somebody's code derived, usually by dividing a discount amount by a base amount, which produces a repeating fraction that then prints at the field's full precision. Find that division in your pricing, rebate or campaign logic and write the stated rate instead of the computed one. If the discount has no clean percentage behind it, the standard does not require one: cbc:MultiplierFactorNumeric is optional, and a discount written as an amount alone, with no percentage and no base amount, is a valid and simpler document. Check as well that your XML writer is not indenting inside the element, because a line break and the spaces after it are characters in the element's text and count towards the six.

The clause that runs

Quoted from the validation-rule stylesheet ZATCA publishes, at the file and line named below. The executed guard is what the check runs; the reported test is what it prints when it fails, and the two are not always the same.

Executed guard

string-length(cbc:MultiplierFactorNumeric) > 0 and not(xs:decimal(cbc:MultiplierFactorNumeric) >= 0 and xs:decimal(cbc:MultiplierFactorNumeric) <= 100 and string-length(substring-after(cbc:MultiplierFactorNumeric,'.')) <=2)

Reported test

xs:decimal(.) >= 0 and xs:decimal(.) <= 100 and string-length(substring-after(.,'.')) <=2
Evaluated against
/ubl:Invoice
Source
vendor/zatca/schematron/20210819_ZATCA_E-invoice_Validation_Rules.xsl:2193

As shipped in ZATCA SDK 3.4.8: the copy quoted here is, byte for byte, the file that release ships. The date in the file name is the name ZATCA gives the file; the rules in it are those of SDK 3.4.8.

A worked example

A synthetic document from the measured test corpus that trips this rule, shown where it differs from one that passed. Mutabiq's report names the class of the value, never the value itself.

Where it differs from a document that passed

  • This example
  • A document that passed
<cbc:ChargeIndicator>false</cbc:ChargeIndicator><cbc:AllowanceChargeReason>Volume discount</cbc:AllowanceChargeReason>This example: <cbc:MultiplierFactorNumeric>10.0000000</cbc:MultiplierFactorNumeric><cbc:Amount currencyID="SAR">10.00</cbc:Amount>This example: <cbc:BaseAmount currencyID="SAR">100.00</cbc:BaseAmount><cac:TaxCategory>  <cbc:ID schemeID="UN/ECE 5305" schemeAgencyID="6">S</cbc:ID>
Document
bad-98-allowance-percentage-seven-decimals.xml
Mutabiq's verdict
Not passed
Reported as
too_many_decimalsmore decimal places than allowed

Download this example (.xml)Check it in Mutabiq

This page's example, checked by the same rules your own upload goes through. No upload and no sign-in.

Rules evaluated against the same part of the document. One wrong value often reports several of them at once.

Check an invoice

Check your own invoice

© 2026 Hayatiq AI Solutions F.Z.E. All rights reserved.