Skip to main content
Version: Latest

14. Troubleshooting

"My Compliance CSID request succeeds, but Production CSID / clearance / reporting calls fail"

Before Phase 0.2, this was a confirmed defect: the four ZATCA client services built Basic-Auth credentials but never attached them to the outgoing request. The Compliance CSID step doesn't require Basic-Auth (it authenticates with the CSR and OTP), so it could succeed independently of the bug — but every step after it does require Basic-Auth, and would have received an unauthenticated-request rejection from ZATCA. This is fixed as of package version 1.0.48. If you observe this on an older package version, upgrade first. See Chapter 7 — Security § 7.2.

"GET api/EInvoicing/Settings/Integration no longer returns my OTP value"

This is expected, as of the Phase 0.2 fix — the endpoint now redacts OTP to null in its response, regardless of caller. ExpiresOn and Invalid are still returned for status/expiry display. If your integration relied on reading the OTP back from this endpoint, it should instead track the OTP value on the caller's own side at the point it was entered. See Chapter 7 — Security § 7.4.

"GET api/EInvoicing/download-file returns 400 for a filename I expect to exist"

As of Phase 0.2, the endpoint rejects any fileName value that isn't a bare filename (no path separators, no .. traversal sequences) — it compares the sanitized name against your input and rejects on any mismatch, rather than silently truncating it. If your filename genuinely contains a directory separator or similar character, it will now be rejected outright rather than partially processed. Confirm the exact filename written by InvoiceSaverService (visible in the SubmittedInvoiceResult.FileName field returned by the Generate call) rather than constructing the name independently. See Chapter 7 — Security § 7.5.

"A rejected invoice's file isn't downloadable, but I know it was written to disk"

This is expected, by design in the current implementation: InvoiceSaverService still writes the XML file for a rejected submission, but the SubmittedInvoiceResult.FileName is nulled for Rejected outcomes — so the download endpoint has no filename to serve even though the file physically exists. See Chapter 10 — Invoice Lifecycle § 10.4.

"My submission failed and I never heard about it again"

Expected — there is no retry mechanism and no notification integration. The caller that made the original POST api/EInvoicing/Generate call receives the outcome synchronously in that same HTTP response; nothing else observes or re-attempts it afterward. See Chapter 12 — Known Limitations.

"Onboarding throws BadRequestException immediately"

OnboardingValidatorService.CheckOnboardingStatus() throws if FatooraSecretSettings.Onboarded == false. This is the expected guard against calling invoice-submission or production-CSID operations before onboarding has completed. Confirm the tenant has completed the full Onboarding flow first.

"The route for the compliance mode toggle 404s — I typed Configuration but the docs say something else"

The live route is api/EInvoicing/Settings/ConfigrationMode — missing the "u" in "Configuration." This is a confirmed, shipped spelling in the controller, not a documentation typo. See Chapter 11 — Technical Debt § 5.

"I need to change the certificate/private key logic and I'm not sure which fork to edit"

Both. Shumoul.Framework.EInvoicing and Shumoul.Framework.EInvoicing.Tenancy are independent, already- drifted copies with no shared core — a fix made in one does not propagate to the other. See Chapter 2 — Architecture § 2.5 and Chapter 11 — Technical Debt § 1.