Error catalogue reference
Every error Notifizz returns has a stable string code so you can match on it programmatically. This page lists the public catalogue: backend HTTP errors, enricher SDK errors, and the HTTP status each maps to.TL;DR
- Backend errors return
{ code: <stable-string>, ... }in the body. - Enricher errors (Node SDK) are typed exception classes —
EnricherInputValidationError,EnricherHmacVerificationError, etc. - HTTP status follows the family (
401for auth,400for input,404for not-found,500for handler failure).
Backend HTTP errors
Authorization (auth/*, authorization/*)
| Code | Status | When |
|---|---|---|
auth/tracking-secret-key | 401 | The sdkSecretKey header is missing, malformed, or doesn’t resolve to an environment. (NoTrackAuthorization) |
auth/invalid-authorization | 403 | The sdkSecretKey did not match any environment. Most common on POST /v1/events/track. (InvalidAuthorization) |
auth/invalid-token-signature | 401 | A widget JWT failed signature verification (Firebase, PubliclySignedJwt). |
auth/invalid-api-key | 401 | The Front API Key in the widget request is unknown. |
auth/no-public-key-registered | 401 | PubliclySignedJwt strategy was selected but the environment has no public key configured in the dashboard. |
auth/invalid-inputs | 400 | A widget auth call (/v1/users/auth) is missing required JWT paths or fields. |
auth/onboarding-not-completed | 403 | The organisation hasn’t finished its onboarding — the surface in question is gated until onboarding completes. |
authorization/organisation-not-authorized-for-this-user | 403 | The dashboard user doesn’t have a role on the target organisation. |
authorization/unauthorizedConfigIdForOrganisation | 404 | A request referenced a configId that belongs to a different organisation. |
HTTP / functional (other/*, notification/*)
| Code | Status | When |
|---|---|---|
other/unknown | 500 | Catch-all for unexpected backend errors. The body’s message field has details. |
notification/config-not-found | 404 | A request referenced a notificationConfigId that doesn’t exist. |
Admin / event (event/*, region/*, organization-settings/*)
| Code | Status | When |
|---|---|---|
event/not-found | 404 | A dashboard request referenced an event id that doesn’t exist. |
event/invalid-name | 400 | An event name failed the grammar (see Event Tracking). Body includes a reason field. |
region/already-set | 409 | The organisation’s region was already chosen and cannot be changed. |
organization-settings/already-exists | 409 | Tried to create org settings for an org that already has them. |
Enricher SDK errors (Node)
The Node SDK (@notifizz/nodejs) ships typed exception classes for the enricher subsystem. client.dispatch(body) encodes them in the response body ({ ok: false, error: { code, message } }) and the Notifizz backend gateway translates error.code back to typed domain errors. The SDK does NOT throw across the dispatch boundary — Promise<DispatchResponse> is the contract. The classes below are the registration-time and internal exceptions you may still want to catch in unit tests.
| Class | Body error.code (when it surfaces from dispatch) | When | |
|---|---|---|---|
EnricherRegistrationError | n/a (thrown synchronously at registration time) | client.enricher() called with a duplicate name, empty name, invalid schema, or missing handler. | |
EnricherInputValidationError | input-invalid (with details) | Incoming params failed the registered input schema. | |
EnricherHmacVerificationError | 401 | missing-header / bad-signature / stale-timestamp | HMAC verification failed. The reason discriminant tells you which check failed. |
EnricherNotFoundError | 404 | enricher-not-found | POST ?name=foo for a name that wasn’t registered on this client. |
EnricherHandlerError | 500 | handler-error | The user-supplied handler threw. The cause field carries the original error. |
| (any other thrown error) | 500 | internal | Catch-all. |
@notifizz/nodejs so you can instanceof-check them in your own logging or error reporting.
Connector webhook errors
Connector webhooks return HTTP-level errors when signature verification fails — there’s no per-provider error code, just the status. See connector webhooks reference for the per-provider details.| Status | When |
|---|---|
401 | Signature verification failed (header missing, secret mismatch, or — for Stripe — timestamp drift). |
404 | The :sourceId in the URL doesn’t exist. |
200 (paused) | Source is paused in the dashboard — Notifizz acks the provider but drops the payload. |
SDK retry behaviour
All three event-tracking SDKs retry transient failures twice (1s, then 2s) before bubbling. Errors that bubble:
- Node — original
axioserror after 3 attempts. - Java —
IOException(the last one) after 3 attempts. - PHP — original
GuzzleHttp\Exception\GuzzleExceptionafter 3 attempts.
403 auth/invalid-authorization) still go through the retry loop today — improvements to short-circuit on permanent failures are tracked separately.
FAQ
`input-validation-failed` from my enricher — what does the body look like?
`input-validation-failed` from my enricher — what does the body look like?
The 400 response carries
{ error: { code: "input-validation-failed", message, details } }. The details field is an array of validation issues — for Zod-derived schemas, it’s the Zod issues array; for raw JSON Schemas, it’s Ajv’s errors array. Read the first entry to see which property failed.`enricher-not-found` but it *is* registered — why?
`enricher-not-found` but it *is* registered — why?
The registry is per-client-instance. If you have two
NotifizzClient instances and only register the enricher on one, dispatch on the other returns { ok: false, error: { code: "enricher-not-found" } }. Make sure the same instance that called enricher() is the one whose dispatch() is wired in the controller.Difference between 400 (`event/invalid-name`) and 422?
Difference between 400 (`event/invalid-name`) and 422?
There is no 422 path on the public endpoints.
400 covers both grammar violations (event name) and DTO validation (class-validator rejecting malformed bodies). Status follows the family — read the code field to disambiguate.What does `other/unknown` actually mean?
What does `other/unknown` actually mean?
A backend exception that didn’t get caught by a more specific handler. Treat it as “infrastructure issue, retry, escalate if persistent”. The
message field has the specific error message; the correlation id (in response headers) lets us trace it.My `EnricherHmacVerificationError` keeps firing despite correct setup.
My `EnricherHmacVerificationError` keeps firing despite correct setup.
Read the
reason field. missing-header means the HMAC headers weren’t sent (the backend usually sends them — if missing, the request didn’t come from Notifizz). bad-signature means the secret mismatches or the body was modified (often a JSON parse + re-serialise breaking the byte-for-byte match). stale-timestamp means clock drift outside ±5 minutes — NTP your enricher host.See also
Event Tracking
Detailed error shapes for
POST /v1/events/track.Enrichers protocol
HMAC verification, input/output schemas.
Connector webhooks
Per-provider signature error semantics.
Troubleshooting
Cross-cutting failure modes — symptom → cause → fix.