BR-KSA-39Seller carries no VAT registration

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-39.

Validate 5 invoices free

Five checks a month on the Free plan. The file is checked in memory and is never stored.

The message ZATCA prints

[BR-KSA-39]-The invoice must contain the seller VAT registration number or seller group VAT registration number (BT-31).

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.

Seller carries no VAT registration

Reported asno_vat_registrationno VAT registration

What is wrong

BR-KSA-39 asks that the seller carry a VAT registration number (BT-31), and in SDK 3.4.8, which rule pack 2.0.0 reads, a document satisfies it one way only: some cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID is non-empty, and some cac:PartyTaxScheme carries a cac:TaxScheme whose cbc:ID is VAT. That does not hold in this document, so ZATCA refuses it. ZATCA's message also names the seller group VAT registration number, and earlier SDK releases (3.0.8) accepted a second route - a non-empty cac:PartyIdentification/cbc:ID with schemeID="HQ" - but SDK 3.4.8 dropped it (KSA:443-444), so an HQ-schemed identification no longer satisfies this rule. Two details of how the check is read. Its two halves are not tied to the same element: a seller with two cac:PartyTaxScheme blocks satisfies it when one holds a non-empty cbc:CompanyID and the other holds the VAT cac:TaxScheme. And the VAT comparison here ignores surrounding whitespace, so a cbc:ID reading VAT with spaces around it is accepted by this rule - which is not how BR-KSA-40 reads the same element. This rule applies to standard and simplified invoices alike.

What to check in your ERP

The seller's VAT number lives in your own company or branch master, so this is a configuration gap rather than a per-document one, and it usually means every invoice from this entity is affected. The causes worth checking, in order: the VAT registration field is empty on the issuing entity, which is common on a branch or legal entity created after the e-invoicing module was configured and on a test company used to produce a sample file; the cac:PartyTaxScheme block is written only when the field is filled, so an empty field removes the whole block rather than leaving an empty element; and the tax scheme identifier is not exactly VAT - values such as Tax, S, or a local scheme name do not satisfy the rule however good the number beside them is. Note also that a seller identification under cac:PartyIdentification does not satisfy this rule, whether its schemeID is CRN, the commercial registration, or HQ: only the tax scheme does.

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:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID) != '' and (cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cac:TaxScheme[normalize-space(cbc:ID) = 'VAT'])))

Reported test

not(((cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID) != '' and (cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cac:TaxScheme[normalize-space(cbc:ID) = 'VAT'])))
Evaluated against
/ubl:Invoice | /cn:CreditNote
Source
vendor/zatca/schematron/20210819_ZATCA_E-invoice_Validation_Rules.xsl:444

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.

Where it differs from a document that passed

  • This example
  • A document that passed
    </cac:Country>  </cac:PostalAddress>A document that passed: <cac:PartyTaxScheme>A document that passed:   <cbc:CompanyID schemeID="HQ">300000000000003</cbc:CompanyID>A document that passed:   <cac:TaxScheme>A document that passed:     <cbc:ID>VAT</cbc:ID>A document that passed:   </cac:TaxScheme>A document that passed: </cac:PartyTaxScheme><cac:PartyLegalEntity>  <cbc:RegistrationName>Hayatiq Test Seller</cbc:RegistrationName>
Document
bad-49-no-seller-vat-registration.xml
Mutabiq's verdict
Not passed
Reported as
no_vat_registrationno VAT registration

Download this example (.xml)Check it in Mutabiq

This page's example, checked by the same rules your own upload goes through. No upload and no sign-in.

Rules evaluated against the same part of the document. One wrong value often reports several of them at once.

Check an invoice

Check your own invoice

© 2026 Hayatiq AI Solutions F.Z.E. All rights reserved.