Error Management Policy
Principles
- Every error has a dedicated page that preserves the application shell (navbar + footer).
- All error pages live under
src/app/[locale]/(app)/event/and share the event layout. - No raw HTML responses are served for routing errors — all failures redirect to event pages.
- Errors are logged server-side before redirecting; client components never need to re-log routing failures.
- Strings on error pages are always rendered in the organization's default language, resolved server-side before the client component receives them.
Error Categories
1. Routing / URL Errors
Caught before any page renders, in middleware or server-side validation.
| Situation | Code | Detected in | Redirects to |
|---|---|---|---|
Locale not supported by the app (e.g. /fr when French is disabled) | locale_not_supported | proxy.js (middleware) | /{en}/event/language?reason=not-available&from={locale} |
| Organization shortname does not exist in the DB | org_not_found | urlValidateServer | /{locale}/event/organization-not-found |
| Organization exists but is blocked | org_blocked | urlValidateServer | /{locale}/event/organization-blocked |
| Locale valid globally but not configured for this tenant | locale_not_configured | [locale]/(app)/layout.jsx and urlValidateServer | /{defaultLocale}/event/language?reason=not-configured&from={locale}&orgName={name} |
Detection layers (in order)
proxy.js(Next.js middleware) — intercepts every request before routing. Redirects unsupported locales (length-2 path segments not insupportedLocales) to the language event page.urlValidateServer(src/lib/url/urlValidateServer.js) — called by route handlers (e.g. PDF download). Validates locale, org existence, org blocked status, and locale configuration. ReturnsNextResponse.redirectto the appropriate event page on failure.[locale]/(app)/layout.jsx— runs for all page requests. Detects MongoDB connectivity failures, locale not configured for the tenant, and ROPA fetch failures. Redirects or renders inline incident components.
2. Event Pages (/(app)/event/)
All event pages share the layout at src/app/[locale]/(app)/event/layout.jsx, which:
- Loads the organization resiliently (silently ignores DB failures).
- Passes an empty ROPA placeholder (
{ ous: [] }) toOrganizationProvidersoMiniDrawerrenders without crashing. - Wraps children with navbar + footer exactly like the main app layout.
| Route | Page file | Component | Use case |
|---|---|---|---|
/{locale}/event/language | event/language/page.jsx | ShowEventDescription | Language not available or not configured |
/{locale}/event/organization-not-found | event/organization-not-found/page.jsx | ShowEventDescription | Org shortname not in DB |
/{locale}/event/organization-blocked | event/organization-blocked/page.jsx | ShowEventDescription | Org is blocked |
The language page reads ?reason (not-available or not-configured) and ?orgName from search params and resolves all strings server-side in the org's default locale before rendering.
Adding a new event page
- Create
src/app/[locale]/(app)/event/{slug}/page.jsx. - The event layout is inherited automatically — no layout file needed in the new directory.
- Add i18n keys to the appropriate namespace (
urlErrorfor org-level errors,Languagesfor locale errors). - Wire the redirect from the detection layer (middleware or
urlValidateServer).
3. Infrastructure Errors
Caught inside [locale]/(app)/layout.jsx, before the main page renders.
| Situation | Component | Behaviour |
|---|---|---|
| MongoDB unreachable or timeout (5 s) | NoMongoDB | Renders full-screen card without navbar (org data unavailable). Shown before any tenant context is established. |
| ROPA document corrupted or missing after org loaded | ResetCorrupted | Renders inline; prompts admin to reset the ROPA. |
These are not redirected to event pages because the org context required to render the event layout may itself be unavailable.
4. Unhandled / Unexpected Errors
| Mechanism | File | Behaviour |
|---|---|---|
| Next.js error boundary | src/app/error.jsx | Catches unhandled runtime errors in the app segment. Renders ErrorComponent with a "Try again" button. Logs to server via logger. |
| Next.js 404 boundary | src/app/not-found.jsx | Catches notFound() calls. Renders NotFoundComponent. |
i18n Namespaces for Error Messages
| Namespace | Used by |
|---|---|
Languages | Language event page (reason=not-available, reason=not-configured), language name labels |
urlError | Organization-not-found and organization-blocked event pages |
All strings on event pages are resolved server-side using getTranslations({ locale: defaultLocale }) so the message is always in the organization's configured default language, regardless of the locale in the URL.
Key Files
| File | Role |
|---|---|
src/proxy.js | Middleware: intercepts unsupported locales |
src/lib/url/urlValidateServer.js | Route-handler URL validation, returns redirect responses |
src/app/[locale]/(app)/layout.jsx | Page-level: MongoDB, ROPA, and locale-configuration checks |
src/app/[locale]/(app)/event/layout.jsx | Shared layout for all event pages |
src/app/[locale]/(app)/event/language/page.jsx | Language error page |
src/app/[locale]/(app)/event/organization-not-found/page.jsx | Org not found page |
src/app/[locale]/(app)/event/organization-blocked/page.jsx | Org blocked page |
src/lib/ui/incidents/ShowEventDescription.jsx | Shared client component for all event page bodies |
src/lib/ui/incidents/NoMongoDB.jsx | MongoDB connectivity error (no navbar) |
src/lib/ui/incidents/ErrorComponent.jsx | Unhandled runtime error boundary component |