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-27.
Five checks a month on the Free plan. The file is checked in memory and is never stored.
The message ZATCA prints
[BR-KSA-27]-The document must contain a QR code (KSA-14), and this code must be base64Binary.
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.
QR code payload is not base64
Reported asmtb_qr_00.not_base64not base64
What is wrong
The QR payload carried in the invoice is not valid base64, so it could not be decoded and none of the QR checks were run. ZATCA rejects this document on the same ground from two directions: the UBL schema types the element as base64 binary, and a payload that is not base64 is not a readable QR code at all.
What to check in your ERP
The element cac:AdditionalDocumentReference with the id QR holds the QR code as base64 text of the TLV byte sequence, not the QR image and not the human-readable values. Check the export step: writing the raw bytes without encoding them, writing a data URI or file path, or writing the text that goes into the QR rather than the encoded payload each produce this. The value is normally produced by the e-invoicing module's own QR generator; if it is being assembled by a report template instead, that is where to look.
QR code payload is empty
Reported asmtb_qr_00.emptypresent but empty
What is wrong
The invoice carries the QR code element but its value is empty, so there is no payload to decode and none of the QR checks were run. ZATCA rejects a simplified invoice whose QR attachment is empty under BR-KSA-27, which requires the element to be present and non-empty.
What to check in your ERP
The element is being written and the value behind it is not, so the mapping is producing the QR block unconditionally while the generator that fills it is not running or is returning nothing. Check that QR generation happens before the document is serialised, and that it is enabled for the document type in question - an e-invoicing module configured for standard invoices only will often leave this empty on a simplified one.
QR code payload ends in the middle of a field
Reported asmtb_qr_00.truncatedends in the middle of a field
What is wrong
The QR payload decoded from base64 is a tag-length-value sequence that ends part way through one of its fields: a field declares more bytes than the payload has left. The payload could not be read, so none of the QR checks were run. Nothing in the published ZATCA rule set decodes the payload, so this is reported as a defect in the QR rather than as something the authority is shown to reject.
What to check in your ERP
The payload has been cut short somewhere between generation and export. The length byte of each field counts bytes, not characters, so the usual cause is a generator that measures Arabic text - the seller name at tag 1 - in characters and writes a length shorter than the bytes that follow. A value column too narrow for the encoded payload, or a truncation applied when the value is stored, will do the same.
QR code payload carries the same tag twice
Reported asmtb_qr_00.duplicate_tagthe same tag appears twice
What is wrong
The QR payload contains two fields with the same tag number. Each tag appears at most once in a ZATCA QR code, so a repeated one means the payload was assembled wrongly and it cannot be read without guessing which of the two is meant. The payload was refused and none of the QR checks were run. Nothing in the published ZATCA rule set decodes the payload, so this is reported as a defect in the QR rather than as something the authority is shown to reject.
What to check in your ERP
This normally comes from a generator that appends fields to a buffer that was not cleared between documents, or from a template that writes the mandatory tags and then a second block that writes some of them again. Check that the payload is built once per invoice, from tag 1 upwards, and that nothing appends to it after it is complete.
QR code payload contains a field tagged zero
Reported asmtb_qr_00.reserved_taga field tagged zero
What is wrong
The QR payload contains a field whose tag number is 0. No ZATCA QR field is tagged zero, and a run of zero bytes is the shape padding or corruption takes, so the payload is treated as unreadable from that point and none of the QR checks were run. Nothing in the published ZATCA rule set decodes the payload, so this is reported as a defect in the QR rather than as something the authority is shown to reject.
What to check in your ERP
Almost always the payload has been padded to a fixed length with zero bytes before it was encoded, so the encoded text is longer than the real payload and the trailing zeros are read as another field. Check whether the buffer the generator writes into is a fixed-size one, and encode only the bytes actually written. The same appears when the payload is stored in a fixed-width binary column.
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
not((cac:AdditionalDocumentReference[normalize-space(cbc:ID) = 'QR'] and exists(cac:AdditionalDocumentReference[normalize-space(cbc:ID) = 'QR']/cac:Attachment/cbc:EmbeddedDocumentBinaryObject) and (normalize-space(cac:AdditionalDocumentReference[cbc:ID = 'QR']/cac:Attachment/cbc:EmbeddedDocumentBinaryObject) != '') and (cac:AdditionalDocumentReference[cbc:ID = 'QR']/cac:Attachment/cbc:EmbeddedDocumentBinaryObject[normalize-space(@mimeCode) = 'text/plain'])) )
Reported test
(cac:AdditionalDocumentReference[normalize-space(cbc:ID) = 'QR'] and exists(cac:AdditionalDocumentReference/cac:Attachment/cbc:EmbeddedDocumentBinaryObject) and (cac:AdditionalDocumentReference/cac:Attachment/cbc:EmbeddedDocumentBinaryObject) != '' and (cac:AdditionalDocumentReference/cac:Attachment/cbc:EmbeddedDocumentBinaryObject[normalize-space(@mimeCode) = 'text/plain']))
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.