BR-KSA-26 Warning — the invoice is accepted

Previous invoice hash (PIH) in the wrong format

The Authority rejects the invoice because the previous invoice hash is not a SHA-256 digest encoded in Base64. Here is how to compute it correctly, and the value the first invoice takes.

The message text as the Authority sends it in English, unedited

If the invoice contains the previous invoice hash (KSA-13), this hash must be base64 encoded SHA256. The hash shall be computed using the following method as described in the ds:transforms block in the XML Invoice Specifications: 1. Remove the <Invoice><ext:UBLExtensions/> block 2. Remove the <Invoice><cac:AdditionalDocumentReference/> block where <cbc:ID/> = QR 3. Remove the <Invoice><cac:Signature/> block 4. Canonicalize the Invoice using the C14N11 standard 5. Hash the resulting string using SHA256 to a binary object 6. Base64 encode the binary object to generate the digest value For the first invoice, the previous invoice hash is "NWZlY2ViNjZmZmM4NmYzOGQ5NTI3ODZjNmQ2OTZjNzljMmRiYzIzOWRkNGU5MWI0NjcyOWQ3M2EyN2ZiNTdlOQ==", the equivalent for base64 encoded SHA256 of "0" (zero) character.

What does this mean?

Every Phase 2 invoice carries the hash of the invoice before it in field KSA-13, so the invoices form a cryptographically linked chain: no invoice can be removed from the middle without breaking the link. This code says the field is there, but its value is not in the required format.

The required format: a 32-byte SHA-256 digest, Base64 encoded — a 44-character string ending in =. Anything else is rejected: a hex digest (64 characters), the raw binary value, or a truncated string.

Why does it happen?

Ordered from the most common to the least — your cause is most likely the first or the second.

  • Emitting the digest as hex instead of Base64 — by far the most common cause. Hex gives 64 characters drawn from 0-9 and a-f, where the rule wants 44 characters of Base64.
  • Hashing the XML file after signing, or before removing the three blocks the specification requires you to remove.
  • Hashing XML that has not been canonicalised with C14N11 — a single space of difference changes the whole hash.
  • Sending 0 or an empty value on the first invoice instead of the Base64 hash of the character 0.
  • Taking the hash from the wrong field of the Authority response to the previous invoice.

How to fix it

3 steps, then send the invoice again.

  1. 1
    Compute the hash in the six steps the specification sets out

    Starting from the XML of the previous invoice: (1) remove the <ext:UBLExtensions> block. (2) Remove the <cac:AdditionalDocumentReference> block whose <cbc:ID> is QR. (3) Remove the <cac:Signature> block. (4) Canonicalise the result with C14N11. (5) Compute SHA-256 over the resulting text as a binary object. (6) Base64 encode that binary object.

  2. 2
    On the first invoice, use the fixed value

    The first invoice has nothing before it, so it takes the fixed value the specification sets: the Base64 of the SHA-256 digest of the character 0: NWZlY2ViNjZmZmM4NmYzOGQ5NTI3ODZjNmQ2OTZjNzljMmRiYzIzOWRkNGU5MWI0NjcyOWQ3M2EyN2ZiNTdlOQ==

  3. 3
    Store the hash of every invoice you send, and never recompute it

    Compute the hash once, at the moment you send, and save it in your database; then use the saved value on the next invoice. Recomputing it later from a stored file that differs slightly in formatting is what breaks the chain after months of correct operation.

This code does not block acceptance, so the invoice you have is compliant. Correct the data so the warnings disappear from future invoices.

Does ZATCA Tools prevent it?

Yes. ZATCA Tools computes the hash, stores it, and links every invoice to the one before it automatically — there is no PIH field for you to fill in, and no step to forget.

Related codes

Frequently asked questions

Does a rejected invoice belong in the chain? +
No. An invoice the Authority rejected was never issued, so its hash does not become the previous hash for the next one. Use the hash of the last invoice that was actually accepted. An invoice accepted with warnings is accepted, and its hash does belong in the chain.
What happens if I issue from two devices at the same time? +
The chain breaks. Each certificate (CSID) has one chain and one counter; if two devices issue on the same certificate at the same moment, both build on the same previous hash and one of the two invoices is rejected. The fix: a separate certificate per device, or serialised issuing from a single point.
Can I verify the hash myself? +
Not from the QR code alone — the code carries the hash, but verifying it needs the full XML. You can read the hash value stored in the code with the QR code reader to confirm it is present and the right length.
You fixed this one — now avoid the next

ZATCA Tools builds the signature, the PIH, the counter and the encoding for you, and validates your data before it is sent. Completely free for now, and no credit card.

Start for free

← All ZATCA error codes