Qoyod
Pricing

Knowledge Base

Error Code 1005: Previous Invoice Hash (PIH) Missing

When your business moves to Phase Two of e-invoicing, each invoice stops being a standalone document. Every invoice becomes a link in an interconnected chain, carrying inside it the hash of the invoice that came before it. This hash, passed from one invoice to the next, is called the Previous Invoice Hash, or PIH for short. One of the most common reasons invoices are rejected when integrating with the Zakat, Tax and Customs Authority (ZATCA) is that this value is missing or wrong, so the Fatoora platform rejects the invoice with error code 1005.

This documentation focuses on one specific error: a missing or invalid PIH value and the break in the hash chain that results from it. We will explain exactly what the error means, how to read the rejection message, the four root causes behind it, and then the steps to fix and prevent it. If you are looking for the full picture of e-invoicing requirements, start from Qoyod’s e-invoicing guide, then come back here to diagnose.

The content is aimed at developers and technical integration specialists who build or integrate invoicing systems with the Fatoora platform. To understand the concept this error revolves around, see the Previous Invoice Hash (PIH)documentation. This error is part of a wider family we explain in the invoice hashing errorsdocumentation, which in turn falls under the Zakat, Tax and Customs Authority e-invoicing errors.

What error code 1005 means

Error code 1005 appears when the PIH value your system sends does not match the hash of the last invoice the platform successfully cleared, or when that value is missing altogether. The platform does not look at the content of the current invoice alone; it also verifies that the field linking it to the one before carries the correct value. Any deviation in this field breaks the chain, so the platform rejects the invoice immediately.

The chain here is not a secondary technical detail. It is the very thing that makes tampering with any old invoice detectable. If someone edited a previously cleared invoice, its hash would change, so it would no longer match the PIH value stored in the next invoice, and the chain would break from the point of the edit through to the last invoice. That is why the platform treats every fault in the PIH as a potential indicator of a broken integrity chain, not a mere formatting error.

The governing rule is simple to state, precise to apply: every invoice carries in its PIH field the hash of the invoice that came before it and was actually cleared. The first invoice alone has no predecessor, so it takes a specific base value defined by the Authority. Any invoice after it takes the hash of the invoice cleared immediately before it. The fault in error code 1005 always lies in one of these two places: the base value in the first invoice, or the link between one invoice and another in the rest of the chain.

What makes this error hard to diagnose is that the hash function is sensitive to the smallest details. Changing a single byte in the previous invoice, however trivial it seems, produces a completely different hash that bears no resemblance to the original. An extra space, a different order of two elements in the XML, or a difference in the encoding of an Arabic character are each enough to flip the hash entirely. So when you chase the root of error code 1005, do not look for a big difference, but for the smallest possible variation in the data that passed through the hash function. This sensitivity is exactly what makes canonicalization an indispensable step before hashing, because it unifies the format and so prevents these subtle differences.

The hash chain and the position of PIH
How each invoice carries the hash of its predecessor.
1

Invoice 1 (base value)

2

Invoice 2: PIH = hash of 1

3

Invoice 3: PIH = hash of 2

A missing or wrong PIH breaks the chain and produces code 1005.
The hash chain: how each invoice links to the one before it
The PIH field in each invoice carries the hash of the invoice cleared immediately before it. Any deviation in this field breaks the chain, so error code 1005 appears.
The first invoice
There is no previous invoice
PIH = the base value
The hash of the empty string encoded in Base64 as defined by the Authority
The second invoice
PIH = hash of the first invoice
NWZlY2ViNjZmZmM4…
Taken from the first invoice after it is actually cleared
The third invoice
PIH = hash of the second invoice
ZjQ4MmFkM2Q3NzAx…
Taken from the second invoice after it is actually cleared
The hash chain in Phase Two of e-invoicing.

How to read the rejection message

Before you diagnose the error, you need to read the platform’s response correctly. The Fatoora platform rejects the invoice with a structured response carrying a status field and a list of error messages. Each error carries a code, a category, and explanatory text. The error we are dealing with here falls in the hashing or sequencing category, and carries a code indicating a PIH mismatch or its absence. The message usually appears in the platform response in this form:

{
  "validationResults": {
    "status": "ERROR",
    "errorMessages": [
      {
        "type": "ERROR",
        "code": "1005",
        "category": "INVOICE-HASHING",
        "message": "Provided PIH is missing or does not match the hash of the last cleared invoice."
      }
    ]
  }
}

The important field here is code which carries the value 1005, and the text explaining that the PIH value sent is either missing or does not match the hash of the last cleared invoice. This message tells you the symptom, not the cause. The cause could be that the field is completely empty, that it carries a value but the wrong one, or that the chain broke before this invoice. Distinguishing these three cases is the first real diagnostic step.

The practical step is to keep a record for each invoice containing three elements: the XML version after canonicalization, the hash computed over it, and the PIH value sent. On any rejection with code 1005, you compare the PIH value you sent with the hash of the last invoice the platform actually cleared. The point of divergence between them shows you directly where the chain broke. Without this record, every diagnosis turns into slow guesswork.

The root causes of error code 1005

Although the symptom is one, the root cause of error code 1005 usually goes back to one of four causes. Each cause needs a different fix, so distinguishing between them saves half the diagnostic time. We will go through them one by one, from the most common in new integration systems to the most subtle.

Cause one: the PIH field is empty or absent

The simplest and most common form of the error at the start of integration is that the system sends the invoice without filling the PIH field at all, or fills it with an empty value. This often happens because the developer built the single-invoice logic before building the chain logic, so the field was left with no source to feed it. The platform expects a value in this field for every invoice without exception, so it rejects an invoice that lacks one with code 1005.

Fixing this cause is straightforward: make sure your system writes a value into the PIH field before canonicalization and signing, and that this value is taken from the correct source. For the first invoice it is the base value, and for every invoice after it, it is the hash of the invoice cleared before it. Add a programmatic check that refuses to send any invoice whose PIH field has no value, so you prevent this error before it reaches the platform.

Cause two: a wrong base value in the first invoice

The first invoice in your system’s life finds no previous invoice to draw its hash from. So the Authority defines a fixed base value that is placed in the PIH field of the first invoice only. This value is the hash of the empty string with the SHA-256 algorithm after encoding it in Base64. The common mistake is that the developer writes it in hexadecimal instead of Base64, or puts zeros in its place, or an empty string.

To understand why this particular value appears, see the Previous Invoice Hash (PIH) documentation that explains its origin. The fix is to place the correct base value as defined by the Authority, and apply it to the first invoice only. Once the first invoice is cleared, the second invoice takes the actual hash of the first, and the base value is never used again after that. The recurring mistake here is that the system applies the base value to every invoice, so the link breaks from the second invoice onward.

Cause three: a counter advanced after a rejected invoice

This is the most deceptive of the causes. When the platform rejects an invoice, the invoice counter must not advance, and the expected PIH value for the next invoice must not change. But some systems increment the counter and save the hash of the rejected invoice as the base for the next invoice. The result is that the next invoice carries in its PIH the hash of an invoice that was never cleared, so the platform rejects it with code 1005.

The golden rule is that the PIH value is built from the hash of the last successfully cleared invoice only, not from the last invoice that was sent. The fix is to separate the sent state from the cleared state in your system. Do not update the PIH source and do not advance the counter until the platform confirms the invoice is cleared. On any rejection, resend the same invoice with the same PIH value, without touching the counter, until it is cleared.

Causes of a missing or wrong PIH
Four roots of a Previous Invoice Hash error.
Causes of error 1005

PIH field empty

Wrong base value for the first invoice

Counter advanced after a rejection without syncing

PIH computed over the wrong data

The first invoice carries the hash of the defined base value.
Four root causes of error code 1005
The symptom is one, but the cause usually goes back to one of four places. Start from the branch closest to your case.
The invoice was rejected with error code 1005
Is the PIH field empty?

Fix: Fill the field before canonicalization with the value taken from the correct source, and add a check that refuses to send with an empty field.

Is it the first invoice?

Fix: Place the base value in Base64 encoding as defined by the Authority, and apply it to the first invoice only.

Did the counter advance after a rejection?

Fix: Build the PIH from the last cleared invoice only, and resend the rejected one without moving the counter.

Is the hash over the wrong data?

Fix: Compute the hash over the XML after canonicalization and before signing, in the encoding the platform expects.

A diagnostic tree for error code 1005 by root cause.

Cause four: a hash computed over the wrong data

Your system may fill the PIH field with a value that exists and is not empty, but is a hash computed over a wrong version of the previous invoice. This happens when you compute the hash before canonicalization, so the bytes differ from the version the platform expects, or when you compute it after adding the signature element, so it includes data that should not enter the computation. The value looks correct in form, but does not match what the platform cleared, so it is rejected with code 1005.

The correct sequence of operations is: generate the XML, then canonicalize, then compute the hash, then sign, then send. The hash carried over to the next invoice must be computed over the canonicalized version before signing, in the same encoding the platform expects. Any change in the order of these steps alters the bytes that pass through the hash function, producing a hash that does not match the reference. For details on this class of errors, see the invoice hashing errors.

Practical fix steps

Now that you know the four causes, here is a practical path that takes you from the rejection message to a cleared invoice. Start from the top and do not move to the next step until you have ruled out the one before it.

The first step is to verify that a value exists in the PIH field at all. Open the sent XML version and look for the field. If it is empty, cause one is the root, and fixing it solves the problem immediately. If you find a value, move to the next step.

The second step is to determine the invoice’s position in the chain. If it is the first invoice in your system, compare the value placed with the base value the Authority defines in Base64 encoding. Any difference means cause two is the root. If it is not the first, move to the next step.

The third step is to review the record of the last invoice actually cleared. Extract its hash as the platform stored it, and compare it with the PIH value you placed in the rejected invoice. If they differ, the cause is either a counter advanced after a rejection, or a hash computed over the wrong data. Check whether your system moved the counter after the last rejection, and whether it followed the correct sequence of canonicalization, hashing, and signing.

The fourth step, after identifying the root and fixing it, is to resend the same rejected invoice with the correct PIH value, without creating a new invoice and without moving the counter. Once the platform clears it, the chain resumes from where it broke, and the following invoices return to the correct order. Be careful not to resend multiple copies of the invoice at the same time, because parallel sending can confuse the clearance order and create a race over the same PIH value.

How to tell error code 1005 apart from its neighbors

Error code 1005 falls within a family of hashing and sequencing errors, some of which carry a symptom close to it. Confusing them leads to a wrong fix that leaves the root in place. So it is worth a minute to distinguish this error from its closest neighbors before you begin the fix.

The closest error to it is the invoice counter mismatch error, usually indicated by the ICV field rather than the PIH field. The difference is that the counter error says the invoice’s order in the chain is unexpected, while error code 1005 says the hash carried over from the previous invoice is incorrect. The two errors may appear together when the counter advances after a rejection, because its advance breaks both the invoice order and the PIH value at once. In that case, fix the shared root, which is separating sending from clearance, and both errors disappear together.

The second neighbor is the hash encoding error, which appears when the PIH value is mathematically correct but written in hexadecimal instead of Base64 or vice versa. This error does not mean a break in the chain, but an error in the format of a single field, and fixing it is only converting the encoding without touching the chain logic. Error code 1005, on the other hand, means the value itself does not match the reference, regardless of its encoding. Distinguishing between them saves you reviewing the entire chain logic when the problem is in a single encoding line.

The third neighbor is signature and certificate errors, which may appear in the same response and confuse the diagnosis. These errors relate to the cryptographic stamp certificate (CSID), not the hash chain, and have a completely independent fix path. When you see multiple messages in a single response, sort them by category first, and treat the hashing category alone when you look for the root of error code 1005.

How to protect your system from this error

Prevention is far cheaper than diagnosis after a rejection occurs. The most important preventive practice is to clearly separate the sent and cleared states for each invoice. Do not update the PIH source and do not advance the counter until clearance is confirmed by the platform. This principle alone prevents the most deceptive of causes, the counter advanced after a rejection.

The second practice is to keep a permanent record for each cleared invoice containing its counter number, its hash, and the PIH value it carried. This record makes rebuilding the chain possible at any moment, and turns any future diagnosis from guesswork into a direct comparison. Mature systems build this record automatically with every clearance.

The third practice is to add programmatic checks before sending: a check that refuses any invoice with an empty PIH field, a check that ensures the base value is applied only to the first invoice, and a check that enforces the correct sequence of the canonicalization, hashing, and signing steps. These checks cost minutes to build and save hours of diagnosis later.

The fourth practice is to build a test environment that simulates the chain before going live on real invoices. Send a series of test invoices, deliberately force a rejection in one of them, and make sure your system resends without moving the counter and without breaking the chain. This exercise reveals flaws in separating sending from clearance before they appear on your customers’ invoices. Systems that skip this step often discover the fault for the first time on a real invoice, which delays their launch.

The fifth practice is to monitor the rejection rate for error code 1005 alone, separately from the rest of the errors. A sudden rise in this code specifically is an indicator of a fault in the chain logic, not in a particular invoice. Catching it early lets you stop sending and address the root before rejected invoices pile up and the fix chain grows long.

Wrong practice versus right practice
How to ensure a correct PIH.
Criterion Right Wrong
PIH source Hash of the previous invoice An old/empty value
First invoice The defined base value A random value
Timing After the previous one is cleared Before syncing
Link the PIH to the hash of the last invoice actually cleared.
Wrong practice versus right practice in chain management
Three decisions make the difference between a sound chain and one that breaks with error code 1005.
The decision Wrong practice Right practice
The source of the PIH value The hash of the last invoice sent The hash of the last invoice successfully cleared
Advancing the counter It advances on every send even if rejected It advances only after clearance is confirmed
Timing of hash computation Before canonicalization or after signing Over the XML after canonicalization and before signing
The base value It is applied to every invoice It is applied to the first invoice only
Hash-chain management rules to avoid error code 1005.
Start today

Let Qoyod manage the hash chain on your behalf

Qoyod handles linking the PIH field, syncing the counter, computing the hash in the correct encoding, and signing automatically, so you never face error code 1005 in the first place.

Try Qoyod for free

How Qoyod helps you

All four causes of error code 1005 arise from the details of manual integration with the Fatoora platform: filling the PIH field, defining the base value, managing the counter, and computing the hash in its correct place. When you use Qoyod, you do not deal with any of these details yourself.

Qoyod is compliant with Phase Two of e-invoicing, and handles the entire chain automatically. It generates an XML version matching the Authority’s specifications, canonicalizes it, then computes the hash over it in the correct encoding and in its correct place before signing. It links the PIH field in each invoice to the hash of the last invoice the platform actually cleared, and fixes the base value for the first invoice only as defined by the Authority.

Most importantly, Qoyod clearly separates the sent state from the cleared state. It does not advance the counter and does not update the PIH source until the Fatoora platform confirms clearance, so it prevents the root of the most deceptive cause. It also manages the cryptographic stamp certificate (CSID) and stores the chain of invoice hashes to verify integrity, so the chain stays intact without any intervention from you. For 24/7 support, the Qoyod team stays available to help you with any question about integration.

Frequently asked questions

What does error code 1005 mean when sending an invoice?

It means the PIH value your system placed in the invoice is missing or does not equal the hash of the last invoice the platform successfully cleared. The platform rejects the invoice because the field linking it to the previous invoice does not carry the correct value, so the chain breaks at this point.

What is the correct value for the PIH field in the first invoice?

It is the base value the Authority defines, which is the hash of the empty string with the SHA-256 algorithm after encoding it in Base64. This value is applied to the first invoice only. The common mistake is writing it in hexadecimal or putting zeros in its place.

Why does the error appear after I resend a rejected invoice?

Usually because your system advanced the counter or updated the PIH source after the rejection, so the next invoice carried the hash of an invoice that was never cleared. The solution is to build the PIH value from the hash of the last cleared invoice only, and to resend the rejected one with the same value without moving the counter.

I sent a PIH value that exists and is not empty, so why is it rejected?

Most likely because it is a hash computed over the wrong data. If you computed the hash before canonicalization or after adding the signature, the bytes differ from what the platform expects. Compute the hash over the XML version after canonicalization and before signing, in the encoding the platform expects.

Does error code 1005 affect subsequent invoices?

Yes, if the cause is a break in the chain rather than an error in a single invoice. Each invoice depends on the hash of its predecessor, so if the chain breaks at one invoice, every invoice after it is affected until the break point is fixed and the invoice there is cleared.

Do I need to handle the PIH value myself when using Qoyod?

No. Qoyod handles filling the PIH field, fixing the base value for the first invoice, syncing the counter, computing the hash in the correct encoding, signing, and integrating with the Fatoora platform automatically. You do not need to write any code or diagnose error code 1005 yourself.

Guides

Continue your learning journey

Explore the rest of Qoyod’s guides, or start applying what you’ve learned.

Live webinars hosted by the Qoyod team to help you use the software easily and answer your questions.

Discover Qoyod’s latest updates, ongoing improvements, and new features in one place.

Our team is ready to help you and provide instant support for any issue you face, around the clock.