BR-CL-03An amount's currency attribute is not a currency code ZATCA accepts

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-CL-03.

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-CL-03]-currencyID MUST be coded using ISO code list 4217 alpha-3

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.

An amount's currency attribute is not a currency code ZATCA accepts

Reported ascurrency_id_not_iso4217the amount's currency is not an ISO 4217 code

What is wrong

An amount element in the document carries a currencyID attribute whose value is not on the ISO 4217 list ZATCA checks against, and the document is refused under BR-CL-03, whose message reads: currencyID must be coded using ISO code list 4217 alpha-3. This is a different field from the one BR-CL-04 reports on: that rule reads cbc:DocumentCurrencyCode, the document's own currency element, while this one reads the currencyID attribute carried on each amount. The check covers thirteen amount element names wherever they appear in the document and at any depth - cbc:Amount, cbc:BaseAmount, cbc:PriceAmount, cbc:TaxAmount, cbc:TaxableAmount, cbc:LineExtensionAmount, cbc:TaxExclusiveAmount, cbc:TaxInclusiveAmount, cbc:AllowanceTotalAmount, cbc:ChargeTotalAmount, cbc:PrepaidAmount, cbc:PayableRoundingAmount and cbc:PayableAmount - so a line's price, a tax subtotal's taxable amount and the document totals are all in scope. An amount that carries no currencyID at all, or an empty one, is not reported by this rule: ZATCA's test requires the attribute to have a length before it looks the value up. A value with a space inside it does fail, because no code on the list contains a space. And the list is ZATCA's own copy of ISO 4217 rather than the current one: it still carries MRO, STD and VEF, which ISO has withdrawn, and not their replacements MRU, STN and VES, so the code ISO publishes today for the Mauritanian ouguiya, the Sao Tome dobra and the Venezuelan bolivar is rejected while the withdrawn one is accepted.

What to check in your ERP

On a domestic invoice every one of these attributes should read SAR. Because the attribute is written on every amount, the usual cause is a single template variable or a default in the serialiser feeding all of them, so one wrong value appears on many elements at once and one correction clears them all. Check where the export takes it from: a currency held on a customer or company record and left blank, a currency symbol or name where the three-letter code belongs, a two-letter country code, and a code written in lower case are the common ones. If the document is genuinely in another currency, check the code against what ZATCA accepts rather than against a current ISO list, for the three currencies above. Keep the value consistent with cbc:DocumentCurrencyCode as well: other rules compare the two, so correcting one and not the other trades this finding for another.

Issue date is longer than ten characters

Reported asissue_date_longer_than_10the issue date is longer than ten characters

What is wrong

The invoice's cbc:IssueDate is more than ten characters long. Only rule packs before 2.0.0 report this under BR-CL-03: SDK 3.0.8 carried an issue-date width assertion under that code, whose message read: field character limit for Issue Date field has been exceeded, the maximum limit for this field is 10. SDK 3.4.8, which rule pack 2.0.0 reads, removed it - BR-CL-03 now checks only the currency code on amounts - and reports a date that is too long under BR-KSA-F-01 instead, on standard and simplified invoices alike, so a report produced under 2.0.0 never carries this note. The length was measured on the value exactly as written, so padding around the date counted toward the limit. The commonest cause is not padding, though: it is a time zone designator or an offset on an otherwise correct date. 2026-09-01Z is eleven characters and 2026-09-01+03:00 is sixteen, and both are legal xs:date values that pass the schema check.

What to check in your ERP

Write the issue date as the date alone, ten characters: 2026-09-01, with no time, no letter Z after it, no offset and no spaces around it. This normally comes from a mapping that writes a full timestamp into a date field, or from a serialiser configured to emit time zone information on every date it writes because the value is stored with a time zone in your system. The time of issue belongs in cbc:IssueTime, which is a separate element - moving the time and the offset there rather than trimming the string is the fix, because they usually carry real information. Check as well that your XML writer is not putting the value on its own indented line: those spaces and line breaks are characters in the element's text and count toward the ten.

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(@currencyID) > 0 and not(((not(contains(normalize-space(@currencyID), ' ')) and contains(' AED AFN ALL AMD ANG AOA ARS AUD AWG AZN BAM BBD BDT BGN BHD BIF BMD BND BOB BOV BRL BSD BTN BWP BYN BZD CAD CDF CHE CHF CHW CLF CLP CNY COP COU CRC CUC CUP CVE CZK DJF DKK DOP DZD EGP ERN ETB EUR FJD FKP GBP GEL GHS GIP GMD GNF GTQ GYD HKD HNL HRK HTG HUF IDR ILS INR IQD IRR ISK JMD JOD JPY KES KGS KHR KMF KPW KRW KWD KYD KZT LAK LBP LKR LRD LSL LYD MAD MDL MGA MKD MMK MNT MOP MRO MUR MVR MWK MXN MXV MYR MZN NAD NGN NIO NOK NPR NZD OMR PAB PEN PGK PHP PKR PLN PYG QAR RON RSD RUB RWF SAR SBD SCR SDG SEK SGD SHP SLL SOS SRD SSP STD SVC SYP SZL THB TJS TMT TND TOP TRY TTD TWD TZS UAH UGX USD USN UYI UYU UZS VEF VND VUV WST XAF XAG XAU XBA XBB XBC XBD XCD XDR XOF XPD XPF XPT XSU XTS XUA XXX YER ZAR ZMW ZWL ', concat(' ', normalize-space(@currencyID), ' ')))))

Reported test

((not(contains(normalize-space(@currencyID), ' ')) and contains(' AED AFN ALL AMD ANG AOA ARS AUD AWG AZN BAM BBD BDT BGN BHD BIF BMD BND BOB BOV BRL BSD BTN BWP BYN BZD CAD CDF CHE CHF CHW CLF CLP CNY COP COU CRC CUC CUP CVE CZK DJF DKK DOP DZD EGP ERN ETB EUR FJD FKP GBP GEL GHS GIP GMD GNF GTQ GYD HKD HNL HRK HTG HUF IDR ILS INR IQD IRR ISK JMD JOD JPY KES KGS KHR KMF KPW KRW KWD KYD KZT LAK LBP LKR LRD LSL LYD MAD MDL MGA MKD MMK MNT MOP MRO MUR MVR MWK MXN MXV MYR MZN NAD NGN NIO NOK NPR NZD OMR PAB PEN PGK PHP PKR PLN PYG QAR RON RSD RUB RWF SAR SBD SCR SDG SEK SGD SHP SLL SOS SRD SSP STD SVC SYP SZL THB TJS TMT TND TOP TRY TTD TWD TZS UAH UGX USD USN UYI UYU UZS VEF VND VUV WST XAF XAG XAU XBA XBB XBC XBD XCD XDR XOF XPD XPF XPT XSU XTS XUA XXX YER ZAR ZMW ZWL ', concat(' ', normalize-space(@currencyID), ' '))))
Evaluated against
cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount
Source
vendor/zatca/schematron/CEN-EN16931-UBL.xsl:1848

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:ID>1</cbc:ID><cbc:InvoicedQuantity unitCode="PCE">1.000000</cbc:InvoicedQuantity>This example: <cbc:LineExtensionAmount currencyID="ABC">100.00</cbc:LineExtensionAmount>A document that passed: <cbc:LineExtensionAmount currencyID="SAR">90.00</cbc:LineExtensionAmount><cac:TaxTotal>  <cbc:TaxAmount currencyID="SAR">15.00</cbc:TaxAmount>
Document
bad-109-currency-id-not-iso4217.xml
Mutabiq's verdict
Not passed
Reported as
currency_id_not_iso4217the amount's currency is not an ISO 4217 code

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.