- Add AML scope note to Handoff - RN Multichain Probe (sanctions-only vs full KYT) - Add human-blocked section with 3 precise next steps for owner - Create Task 11 Pre-flight Inventory: library choice, dev/prod flow, admin UI gaps, backend gaps, risks, acceptance criteria
5.3 KiB
title, tags
| title | tags | |||
|---|---|---|---|---|
| Error Codes |
|
Error Codes
This page documents the error shape returned by the AMN backend and the HTTP status mapping used across services.
Standard error shape
The canonical helper is ResponseHandler.error in backend/src/shared/utils/response-handler.ts. Modern routes return:
{
"success": false,
"message": "Validation failed",
"error": "Validation Error",
"statusCode": 400,
"timestamp": "2026-05-23T10:00:00.000Z",
"path": "/api/auth/register",
"method": "POST",
"data": [ /* field-level details for validation errors */ ]
}
Uncaught errors are formatted by shared/middleware/errorHandler.ts:
{
"success": false,
"error": "Internal Server Error",
"statusCode": 500,
"stack": "..." // only in NODE_ENV=development
}
Legacy routes (chiefly /api/users legacy paths, /api/marketplace legacy paths, and /api/payment/decentralized/*) return ad-hoc shapes such as { "error": "..." } or { "success": false, "message": "..." }. Treat any non-2xx response as an error and read whichever of error / message is present.
HTTP status mapping
| Status | When | Examples |
|---|---|---|
200 OK |
Successful read or mutation | Most GETs, idempotent PUTs/PATCHs |
201 Created |
Resource created | POST /api/marketplace/purchase-requests, POST /api/auth/register (when user created), POST /api/marketplace/reviews |
202 Accepted |
Async accepted (provider webhooks) | Request Network webhook accepted while safety checks are pending |
204 No Content |
Mutations with no body to return | Rare — most endpoints return the updated object |
400 Bad Request |
Validation failure, malformed input | express-validator errors, bad MongoIds, missing fields |
401 Unauthorized |
Missing or invalid JWT | Access token required, Invalid or expired token |
403 Forbidden |
Authenticated but not allowed | Role check failed, email not verified, ownership check failed |
404 Not Found |
Resource (or route) missing | notFoundHandler, Resource not found from ResponseHandler.notFound |
409 Conflict |
Duplicate / state collision | USER_EXISTS, duplicate review, dispute already open |
423 Locked |
Account temporarily locked | After repeated failed logins (Redis-tracked) |
429 Too Many Requests |
Rate limit hit | Currently issued only by per-feature Redis limits (auth / AI); global limiter is disabled |
500 Internal Server Error |
Unhandled exception | Caught by errorHandler; included stack trace in dev |
502 Bad Gateway |
Upstream provider failure | OpenAI / Request Network unreachable |
Application error codes
The error field of the response envelope contains a human-readable category. Currently used codes:
| Code | Meaning | Returned by |
|---|---|---|
Validation Error |
express-validator rejected the body |
All *Validation middlewares |
Not Found |
Generic resource lookup miss | ResponseHandler.notFound |
Unauthorized |
No token / bad token | authenticateToken, ResponseHandler.unauthorized |
Forbidden |
Role/ownership check failed | authorizeRoles, ResponseHandler.forbidden |
Internal Server Error |
Catch-all 500 | ResponseHandler.internalError, errorHandler |
USER_EXISTS |
Email already registered | POST /api/auth/register |
For auth-specific 4xx responses the body's message carries the user-facing text (often Persian/Farsi for legacy reasons):
"کاربری با این ایمیل قبلاً ثبتنام کرده است"- email already in use (409)"کد تحویل نادرست است"- wrong delivery code (400)"شما مجاز به ایجاد کد تحویل برای این درخواست نیستید"- not the buyer (403)
Mongoose-specific mappings
Handled in errorHandler:
| Mongoose error | Mapped status | Body message |
|---|---|---|
ValidationError |
400 | Validation Error |
MongoError code 11000 |
409 | Duplicate resource |
JsonWebTokenError |
401 | Invalid token |
TokenExpiredError |
401 | Token expired |
Webhook-specific
| Provider | Endpoint | Status on success | Status on signature mismatch |
|---|---|---|---|
| Request Network pay-in | POST /api/payment/request-network/webhook |
200 { success: true } or 202 while safety checks are pending |
401 { success: false } |
| Generic payment callback | POST /api/payment/callback |
200 { success: true, message } |
400 |
If a webhook is acknowledged with non-2xx, the provider may re-deliver. Persisting delivery evidence and replay support is a launch-hardening item in Request Network Integration Constraints.
Client guidance
- Always parse
response.json()even on non-2xx — bothmessageanderrorare useful for UX surface text. - For optimistic UI, treat
409as "your action raced — refresh". - For
401, attempt one silent refresh-token call before redirecting to sign-in. - For
403, do not retry — the user lacks permission. - For
423, surface the lockout window from themessage/dataand direct the user to password reset.