BR-KSA-29Signature block does not carry the required signature id
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-29.
Five checks a month on the Free plan. The file is checked in memory and is never stored.
The message ZATCA prints
[BR-KSA-29]-If the cryptographic stamp (KSA-15) exists in the invoice, this cryptographic stamp (KSA-15) must contain the exact "urn:oasis:names:specification:ubl:signature:Invoice" value for referenced signature ID and signature ID.
Also cited in this report
BR-KSA-28
[BR-KSA-28]-If the cryptographic stamp (KSA-15) exists in the invoice, this cryptographic stamp (KSA-15) must contain the exact "urn:oasis:names:specification:ubl:signature:1" value for signature information ID.
BR-KSA-60
[BR-KSA-60]-Cryptographic stamp (KSA-15) must exist in simplified tax invoices and associated credit notes and debit notes (KSA-2, position 1 and 2 = 02).
BR-KSA-27
[BR-KSA-27]-The document must contain a QR code (KSA-14), and this code must be base64Binary.
BR-KSA-30
[BR-KSA-30]-The document cryptographic stamp (KSA-15) must contain the exact "urn:oasis:names:specification:ubl:dsig:enveloped:xades" value for signature method.
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.
Signature block does not carry the required signature id
Reported assignature_id_mismatchnot the required signature id
What is wrong
This is a simplified invoice, and no cac:Signature in it carries a cbc:ID whose value is exactly urn:oasis:names:specification:ubl:signature:Invoice. SDK 3.4.8 flags the document under BR-KSA-29 as a warning, not a rejection: the finding is reported without failing the document by itself. That value is a fixed UBL identifier and nothing more: it is not computed, it is not derived from anything in this invoice, and it has no connection to the cryptographic stamp, to a certificate or to a private key. Your ERP writes it out literally and the check is a plain string comparison against it, so a URN with a segment changed, a truncated one, one written in a different case, an id borrowed from another standard, and a document carrying no cac:Signature at all, all fail in exactly the same way. The comparison is made over every cac:Signature in the document, at any depth, and one block carrying the required value satisfies it - a second block elsewhere, such as one hanging off a line item's certificate, may legitimately carry an id of its own. Read a silent BR-KSA-60 carefully: that rule asks only that a cac:Signature exists and is not empty, so a block carrying the wrong id passes BR-KSA-60 and still draws this warning here. ZATCA's message for this rule calls the requirement the cryptographic stamp (KSA-15); the check behind it does not test a stamp. The rule applies to simplified invoices and their credit and debit notes - the invoice transaction code KSA-2 beginning 02.
What to check in your ERP
Write the constant, exactly: cbc:ID inside cac:Signature, with the text urn:oasis:names:specification:ubl:signature:Invoice, letter for letter and in that case. It can be written unconditionally from the export template, because it never varies from one invoice to the next and does not depend on the signing step having run. ZATCA's own sample simplified invoices carry it beside cbc:SignatureMethod with the value urn:oasis:names:specification:ubl:dsig:enveloped:xades; check that one while you are there, since it is the neighbouring rule BR-KSA-30 and fails separately. The usual causes are a template that fills this element with something invoice-specific such as the invoice number or a generated id, a generic UBL library that emits a signature reference with a default id of its own, a value retyped by hand with a segment misspelt, and a template copied from a pre-Phase-2 sample. If the document carries no cac:Signature at all you will see BR-KSA-60 beside this finding; adding the block with both constants in it closes both.
Cryptographic stamp does not reference the invoice signature
Reported asreferenced_signature_id_mismatchdoes not reference the invoice signature
What is wrong
The referenced signature ID inside the cryptographic stamp (sac:SignatureInformation/sbc:ReferencedSignatureID, under ext:UBLExtensions) is missing, or is not urn:oasis:names:specification:ubl:signature:Invoice. BR-KSA-29 requires both that element and cac:Signature/cbc:ID to carry exactly that value. ZATCA flags this as a warning, which does not by itself reject the document. On a simplified invoice that has not been signed yet the stamp does not exist, so this note is expected until the invoice is signed.
What to check in your ERP
If your e-invoicing solution signs the invoice, check that the signing step writes the value into both places unchanged. If you are checking the XML before it is signed, this note goes away once the signature is added.
An attachment on this invoice carries no payload element
Reported aspayload_element_missingthe payload element is missing
What is wrong
Only rule packs before 2.0.0 report this. In SDK 3.0.8, BR-KSA-29 was written as three conditions and only the third was about the signature id; the first two were about attachments: ZATCA evaluated the rule once for every cac:AdditionalDocumentReference/cac:Attachment in the document except the previous invoice hash one, and each of them had to carry a cbc:EmbeddedDocumentBinaryObject that is not empty. Here one of those attachments - on a simplified invoice this is normally the QR code attachment - has no payload element inside it at all, which failed the rule on that condition. In SDK 3.4.8, which rule pack 2.0.0 reads, BR-KSA-29 no longer looks at the attachment's payload (KSA:1341-1344): it compares the signature id and the cryptographic stamp's referenced signature id, as a warning, so a report produced under 2.0.0 never carries this note. The defect itself is still reported: BR-KSA-30 kept both payload conditions and refuses the document on them, and the QR rules report the same element. This note is not evidence that anything is wrong with your cac:Signature block.
What to check in your ERP
Fix the attachment, not the signature block. The shape is two levels inside the reference: a cac:Attachment, and a cbc:EmbeddedDocumentBinaryObject inside that, with the base64 payload as its text content. The usual causes are a template that writes the reference and its cbc:ID from one loop and the attachment from another that did not run, a value written into the reference's own text or into a description element instead of into the attachment, and a nesting level dropped so that the binary object sits directly under the reference. If your export writes some document reference of its own beside the QR one, a delivery note or a contract say, that attachment is judged by BR-KSA-30 too, so a block written without its payload for a purpose of your own reaches that rule as well. A payload element that is present but empty is a different finding.
An attachment on this invoice has an empty payload
Reported aspayload_emptythe payload is empty
What is wrong
Only rule packs before 2.0.0 report this. In SDK 3.0.8, BR-KSA-29 was written as three conditions and only the third was about the signature id; the first two were about attachments: ZATCA evaluated the rule once for every cac:AdditionalDocumentReference/cac:Attachment in the document except the previous invoice hash one, and each of them had to carry a cbc:EmbeddedDocumentBinaryObject that is not empty. Here one of those attachments - on a simplified invoice this is normally the QR code attachment - carries the payload element with nothing in it, which failed the rule on that condition: emptying the QR payload of an otherwise passing simplified invoice returned BR-KSA-28, BR-KSA-29 and BR-KSA-30 from SDK 3.0.8. In SDK 3.4.8, which rule pack 2.0.0 reads, BR-KSA-29 no longer looks at the attachment's payload (KSA:1341-1344): it compares the signature id and the cryptographic stamp's referenced signature id, as a warning, so a report produced under 2.0.0 never carries this note. The defect itself is still reported: BR-KSA-30 kept both payload conditions and refuses the document on them, and the QR length rule reports an empty QR payload as well. This note is not evidence that anything is wrong with your cac:Signature block.
What to check in your ERP
The element is being written and the value behind it is not, so the mapping produces the attachment unconditionally while the step that fills it is not running or is returning nothing. On a simplified invoice that step is normally the QR generator: check that it runs before the document is serialised and that it is enabled for this document type. Fix the generator or the mapping rather than deleting the empty element, because deleting the QR block moves the document onto BR-KSA-27 for a missing QR reference instead. Your cac:Signature block needs no change for this note, but it is worth confirming that its cbc:ID and cbc:SignatureMethod carry the two fixed URNs while you are there: BR-KSA-30 only reaches its signature method condition once the payload is filled, so a wrong URN can be waiting behind the payload defect.
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:Signature/cbc:ID) = 'urn:oasis:names:specification:ubl:signature:Invoice' and (normalize-space(//ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sig:UBLDocumentSignatures/sac:SignatureInformation/sbc:ReferencedSignatureID)) = 'urn:oasis:names:specification:ubl:signature:Invoice' )
Reported test
exists(cbc:EmbeddedDocumentBinaryObject) and (cbc:EmbeddedDocumentBinaryObject) != '' and (//cac:Signature/cbc:ID) = 'urn:oasis:names:specification:ubl:signature:Invoice'
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.