Invocie

Top 7 ZATCA Rejection Reasons (and How to Fix Them)

From clock drift to malformed VAT numbers, these are the rejections we see most often in production — with the fix for each.

Invocie Team · 18 dicembre 2025 · 4 min di lettura


ZATCA rejects invoices with terse error codes, and decoding them under deadline pressure is brutal. Here are the top seven we see in production, ordered by frequency, with a tested fix for each.

1. ENT_ICV-001 — Invoice Counter Value out of sequence

ICV must increase monotonically per device. The cause is almost always parallel issuance from two processes against the same EGS. Fix: serialize ICV assignment behind a single source of truth (a database sequence works).

2. ENT_PIH-002 — Previous Invoice Hash mismatch

The hash you submitted as the previous one doesn't match what ZATCA has on file. Cause: someone re-submitted an old invoice or the local cache fell behind. Fix: query Fatoora for the latest cleared hash and reseed your chain.

3. KSA-25 — Tax category code missing or invalid

Each line item needs a UNCL5305 category code: S, Z, E, O, or AE. Common slip: leaving it blank for zero-rated lines. Fix: explicitly emit Z (not omit it).

4. KSA-12 — Seller VAT number malformed

Saudi VAT registration numbers are 15 digits and start with 3, ending with the checksum. A common mistake is submitting the 10-digit Commercial Registration number instead. Fix: pull the VAT from the tax_registrations table by kind='VAT', not from the trade-license field.

5. CLOCK_DRIFT — IssueDateTime more than 30 seconds out of sync

Server clock skew. Fix: NTP sync to pool.ntp.org, every minute, on every host that issues invoices.

6. KSA-08 — Standard invoice missing buyer VAT

B2B invoices in KSA require the buyer's VAT number (TaxID). Simplified (B2C) invoices do not. Fix: branch on InvoiceTypeCode (388 = standard, 388 with subtype 02 = simplified) in your serializer.

7. KSA-19 — Tax amount inconsistent with line totals

Sum of line tax amounts ≠ TaxTotal. Cause is almost always rounding mid-calculation. Fix: round only the final per-rate subtotal (banker's rounding), never per-line.


Letture correlate

Emetti fatture conformi in ogni mercato

ZATCA, FTA, Peppol e post-audit globale — un'unica API.

Parla con il nostro team