Guides
Error Handling
The SDK throws structured AfricaZKError instances with stable error codes. Map each one to the right user-facing message and recovery path.
Error codes
| Code | Thrown by | Cause | Recovery |
|---|---|---|---|
| INVALID_INPUT | verifyIdentity() | idType / idNumber / dob failed format validation | Show inline form errors; user fixes input |
| BACKEND_FAILED | verifyIdentity() | Dojah could not confirm the ID | Show banner; suggest user double-check NIN/BVN |
| CIRCUIT_FAILED | generateProof() | Constraints failed (age < 18 or invalid signature) or WASM error | Restart from verifyIdentity() |
| PROOF_REJECTED | submitProof() | Anchor program rejected the proof or public key | Restart from verifyIdentity() — proof was tampered or stale |
| DUPLICATE_NULLIFIER | submitProof() | Identity already attested to another wallet | Direct user to use the existing verified wallet — cannot proceed |
| USER_REJECTED | submitProof() | User cancelled the wallet signature | Show retry button; no state changed |
| RPC_FAILED | submitProof() / checkAttestation() | RPC node unreachable or timed out | Retry with exponential backoff; offer manual retry after 3 fails |
Recommended pattern
error-router.ts
import { AfricaZKError } from '@africazk/identity'
try {
await runFlow()
} catch (e) {
if (e instanceof AfricaZKError) {
switch (e.code) {
case 'INVALID_INPUT': return showFormError(e.message)
case 'BACKEND_FAILED': return showBanner('Verification failed — check your details')
case 'CIRCUIT_FAILED': return showBanner('Proof generation failed — please reload')
case 'PROOF_REJECTED': return showBanner('Proof was rejected on-chain')
case 'DUPLICATE_NULLIFIER': return showFinal('This identity already has a verified wallet')
case 'USER_REJECTED': return showRetry('You cancelled the wallet signature')
case 'RPC_FAILED': return showRetry('Network error — please try again')
}
} else {
showBanner('Something unexpected happened')
console.error(e)
}
}Default to friendly, not technical
Users do not care about "BACKEND_FAILED". They care that they couldn't verify. Translate every code into a sentence a non-technical user can act on, and put the raw code into a small "details" toggle for support tickets.When to retry automatically
- RPC_FAILED — yes, with exponential backoff (1s, 2s, 4s, then surface).
- BACKEND_FAILED — no. The user input failed Dojah verification; retrying with the same input gives the same result.
- CIRCUIT_FAILED — no. The credential is dead; restart from verifyIdentity().
- USER_REJECTED — no. Wait for the user to click retry. Auto-retrying re-pops the wallet and annoys.
Errors you should never see in production
If you see PROOF_REJECTED with valid SDK inputs, something is wrong: either the SDK is out-of-date relative to the deployed program, or the local proof verifier is broken. Open an issue.