ZATCA E-Invoicing Phase 2 Rejection Codes: Fixes That Work
When the Fatoorah portal spits back your invoice, you need the exact rejection code, its root cause, and the fix — not a generic compliance checklist. Here is the field guide working accountants in KSA actually need.
By the SuperAccountant Editorial Team
Your invoice hit the Fatoorah portal and came back rejected. The timestamp is ticking — under ZATCA's Implementing Regulations, a cleared tax invoice must carry a valid QR code and cryptographic stamp before it reaches the buyer, and every minute of delay is a potential compliance gap. Most guides will tell you to "ensure your ERP is compliant." This one tells you exactly which rejection code you received, why it fired, and what to change before your next submission.
Why Phase 2 Rejections Are Different From Phase 1
Phase 1 (Generation) required structured XML and a QR code on the invoice face. Phase 2 (Integration) introduced a real-time API handshake between your Fatoorah-compliant ERP and ZATCA's Fatoorah portal. The portal now validates every field against the UBL 2.1 schema, applies cryptographic checks (digital signature via CSID — Cryptographic Stamp Identifier), and runs business-rule validations before it either clears or rejects the document.
This means rejection is no longer a human reviewer's decision — it is an automated engine returning a structured error object. According to the official ZATCA portal (zatca.gov.sa), the response payload includes an errorCode, a category, and a human-readable message in both Arabic and English. Knowing which layer the error lives in — schema, business rule, or security — determines your fix path.
The Three Error Categories You Will See
ZATCA groups validation failures into three categories, each with different severity and remediation logic:
| Category | Label | Effect on Invoice | Typical Trigger |
|---|---|---|---|
| BV | Business Validation | Invoice rejected — must be corrected and resubmitted | Missing mandatory field, wrong VAT rate, incorrect invoice type code |
| XSD | XML Schema Validation | Invoice rejected — structural failure | Malformed XML, missing namespace declaration, wrong element order |
| WARNING | Non-blocking | Invoice cleared with warnings | Recommended (not mandatory) fields absent |
Warnings do not block clearance, but they accumulate in your compliance profile. BV and XSD errors result in a hard rejection — the invoice does not receive a ZATCA stamp and cannot legally be issued to the buyer.
The Most Common Rejection Codes and Their Exact Fixes
BV-S-002 — Invalid VAT Registration Number
What fires it: The seller's VAT number in cac:PartyTaxScheme/cbc:CompanyID does not match the registered VAT number on the CSID certificate used to sign the document.
Fix: Cross-check the VAT number in your ERP's company master against your ZATCA portal profile under My Account → Certificates. A single transposed digit causes this. After correcting the master data, regenerate the CSID if the certificate was issued under the wrong number.
BV-S-005 — Invoice Date in the Future or Missing Hijri Date
What fires it: ZATCA's Implementing Regulations (Article 53) require the invoice date (cbc:IssueDate) in Gregorian format and the Hijri date in the cbc:Note or the designated extension field, depending on your ERP's implementation of the ZATCA SDK.
Fix: Confirm your ERP is appending the Hijri date. For example, an invoice dated 14 June 2025 (Gregorian) should carry 17 Dhul Hijjah 1446 (Hijri). Most Mu'tamad ERPs handle this automatically — if you are seeing BV-S-005, check whether a recent ERP update changed the date serialisation format.
BV-VAT-047 — VAT Amount Mismatch
What fires it: The calculated VAT amount at line level does not reconcile with the document-level total within the 0.01 SAR rounding tolerance ZATCA permits.
Fix: This is almost always a rounding-order issue. ZATCA's Business Rules require VAT to be calculated on the line net amount first, then summed — not calculated on the grand total. If your ERP calculates VAT on the invoice total and then distributes it to lines, a 50-line invoice can accumulate a rounding gap large enough to trigger this code. Raise a configuration ticket with your ERP vendor referencing ZATCA's KSA Business Rules document (available at zatca.gov.sa under the Fatoorah developer portal).
XSD-VAT-E — Schema Validation Failed on cac:TaxTotal
What fires it: The XML element cac:TaxTotal is either absent, appears more than twice, or the child elements are in the wrong sequence. UBL 2.1 is strict about element ordering.
Fix: Run your XML through ZATCA's offline SDK validator before portal submission. The SDK flags the exact line number. Common cause: a developer manually edited an XML template and moved cbc:TaxAmount above cac:TaxSubtotal, reversing the required sequence.
BV-S-029 — Duplicate Invoice Reference
What fires it: You are submitting an invoice with a UUID or cbc:ID that has already been cleared or recorded by ZATCA. This frequently happens after a system outage when the ERP retries a submission without checking whether the first attempt succeeded.
Fix: Before resubmitting after any connection failure, query the ZATCA portal API endpoint GET /invoices/{uuid} to confirm whether the original submission was processed. If it was cleared, issue a credit note referencing the original invoice — do not resubmit the same UUID.
BV-S-033 — Previous Invoice Hash Mismatch (Chain Break)
What fires it: ZATCA Phase 2 requires each invoice to include the hash of the previous invoice (PIH) in the cryptographic chain. If your sequence is broken — for example, because a rejection caused a gap — the PIH on your next invoice will not match what ZATCA holds.
Root cause and fix: This is the most operationally disruptive error in Phase 2. When invoice N is rejected, invoice N+1 must still reference invoice N's hash (even though N was rejected) because ZATCA recorded the attempt. Your ERP must store the last-submitted hash regardless of clearance status. If your ERP is not doing this, escalate to your vendor immediately — this is a core Phase 2 requirement under ZATCA's technical specifications, Section 6.3 of the developer guide on zatca.gov.sa.
Your Pre-Submission Checklist
Run this before every batch submission, especially after any ERP upgrade or system change:
- VAT registration number in XML matches CSID certificate exactly
- Both Gregorian and Hijri dates present and correctly formatted
- VAT calculated line-by-line, not on invoice total
- XML validated against UBL 2.1 schema using ZATCA offline SDK
- UUID is unique — no prior submission with same reference
- Previous Invoice Hash (PIH) sourced from last submitted invoice (cleared or rejected)
- Invoice type code correct:
388for standard tax invoice,381for credit note,383for debit note - Supplier IBAN present on B2B invoices (required field in Phase 2 for invoices above ﷼ 1,000)
- CSID certificate is valid and not expired (check expiry in your ERP certificate store)
How to Escalate When the Fix Is Not Obvious
If you have corrected all apparent fields and the same rejection code persists:
- Export the full API response payload — not just the human-readable message. The
validationResultsarray contains sub-codes your ERP's UI may be suppressing. - Reproduce with the ZATCA SDK simulator — available on the Fatoorah developer portal at zatca.gov.sa. This isolates whether the issue is in your XML or in your API authentication headers.
- Check your CSID certificate chain — ZATCA's Integration tier uses a two-certificate model (Compliance CSID and Production CSID). Submitting production invoices signed with a Compliance CSID is a silent failure mode that surfaces as a cryptographic rejection.
- File a support ticket via the ZATCA portal with the UUID, the rejection timestamp, and the full error JSON. ZATCA's support SLA for Phase 2 integration issues is documented on their portal; referencing the UUID accelerates resolution.
If you want to benchmark your understanding of Phase 2 mechanics against real exam-standard questions, the ZATCA module on SuperAccountant's practice quiz covers clearance workflow, error taxonomy, and business rule logic in exam-ready format.
Building a Rejection Log: Your Compliance Evidence
Every rejected invoice is a potential audit data point. ZATCA's audit trail requirements mean you should maintain a structured rejection log that records: the invoice UUID, rejection timestamp, error code received, corrective action taken, resubmission UUID, and final clearance confirmation. This log serves two purposes — it demonstrates good-faith compliance effort if ZATCA queries a gap in your invoice sequence, and it surfaces patterns (the same BV code appearing repeatedly signals a systematic ERP configuration issue, not a one-off data entry error).
Accountants sitting in the accounts payable or accounts receivable function should treat this log with the same rigour as a VAT return reconciliation file. Under ZATCA's penalty framework, repeated failures on the same code class can escalate from warnings to formal non-compliance findings.
For teams looking to formalise this workflow and upskill on Phase 2 integration as a practice area, the SuperAccountant jobs board regularly features KSA roles where Phase 2 expertise commands a meaningful salary premium — practical evidence that this skill set has tangible market value right now.
Sharpen your edge with SuperAccountant's next live cohort — small batches, real client workpapers, taught by partners. Details and seats at https://app.superaccountant.in/en/cohort.