Overview
Error responses are currently unstructured — some endpoints return { error: '...' }, others return HTML Express default errors, and unhandled exceptions leak stack traces. A consistent error format is required for reliable client-side error handling.
Standard Error Response
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Asset code must be 1–12 uppercase alphanumeric characters",
"details": {
"field": "assetCode",
"received": "xlm!!!",
"constraint": "regex"
},
"request_id": "req_01hx3k..."
}
}
Error Codes
| Code |
HTTP |
Meaning |
VALIDATION_ERROR |
400 |
Request schema failure |
UNAUTHORIZED |
401 |
Missing or invalid API key |
NOT_FOUND |
404 |
Resource does not exist |
RATE_LIMITED |
429 |
Too many requests |
UPSTREAM_ERROR |
502 |
All price sources failed |
INTERNAL_ERROR |
500 |
Unexpected server error |
Implementation
- Create
src/errors/AppError.js:
class AppError extends Error {
constructor(code, message, statusCode, details = {}) { ... }
}
- Create central error middleware in
src/middleware/errorHandler.js:
function errorHandler(err, req, res, next) {
const isAppError = err instanceof AppError;
const status = isAppError ? err.statusCode : 500;
const code = isAppError ? err.code : 'INTERNAL_ERROR';
const message = isAppError ? err.message : 'An unexpected error occurred';
// Never leak err.stack to client in production
res.status(status).json({ error: { code, message, request_id: req.id } });
}
- Attach
request_id (nanoid) to every request via middleware.
Acceptance Criteria
Overview
Error responses are currently unstructured — some endpoints return
{ error: '...' }, others return HTML Express default errors, and unhandled exceptions leak stack traces. A consistent error format is required for reliable client-side error handling.Standard Error Response
{ "error": { "code": "VALIDATION_ERROR", "message": "Asset code must be 1–12 uppercase alphanumeric characters", "details": { "field": "assetCode", "received": "xlm!!!", "constraint": "regex" }, "request_id": "req_01hx3k..." } }Error Codes
VALIDATION_ERRORUNAUTHORIZEDNOT_FOUNDRATE_LIMITEDUPSTREAM_ERRORINTERNAL_ERRORImplementation
src/errors/AppError.js:src/middleware/errorHandler.js:request_id(nanoid) to every request via middleware.Acceptance Criteria
AppErrorclass created with all codes aboverequest_idon every response (success and error)throw new AppError(...)