Error Handling
Robust error handling is essential for creating reliable APIs. Jetpath centralizes error handling in middleware for consistent error management.
Philosophy
Instead of scattered try...catch
blocks, Jetpath’s approach relies on:
- Signaling Errors: Using
throw new Error()
- Centralized Catching: Intercepting errors in middleware
- Standardized Responses: Sending consistent error responses
Throwing Errors
When processing cannot continue normally, signal an error using ctx.send(error, <status code>)
.
Using ctx.send(error, <status code>)
-
Common Status Codes:
400 Bad Request
: Validation errors401 Unauthorized
: Authentication issues403 Forbidden
: Permission denied404 Not Found
: Resource not found500 Internal Server Error
: Unexpected issues
-
Examples:
// Resource Not Found if (!pet) { ctx.send(`Pet ${ctx.params.id} not found`, 404); }
// Unauthorized Access if (!ctx.plugins.verifyAuth(ctx).authenticated) { ctx.set("WWW-Authenticate", "Bearer realm="protected""); ctx.send("Authentication required", 401); }
// Forbidden Action if (ctx.app.user?.role !== 'admin') { ctx.send("Admin privileges required", 403); }
// Validation Error try { const data = ctx.validate(RequestSchema); } catch (err) { ctx.send(err.message, 400); }
// Simple Not Found ctx.send("",404);
Using throw new Error()
For unexpected internal errors:
try {
const result = await riskyOperation();
} catch (error) {
console.error("Internal error:", error);
throw new Error("Internal processing error");
}
Middleware Error Handling
The post-handler function in middleware handles errors from route handlers and validation.
Error Handling Structure
return (ctx, err?: Error) => {
if (err) {
// 1. Log error
console.error({
message: `Request Error: ${err.message}`,
stack: err.stack,
requestId: ctx.get("X-Request-ID"),
url: ctx.request.url,
method: ctx.request.method,
});
// 2. Set status code
ctx.code = ctx.code >= 400 ? ctx.code : 500;
// 3. Format response
const errorMessage = (ctx.code >= 500 && process.env.NODE_ENV === 'production')
? "Internal Server Error"
: err.message || "An unexpected error occurred";
const errorResponse = {
error: {
message: errorMessage,
code: ctx.code,
requestId: ctx.get("X-Request-ID"),
},
timestamp: new Date().toISOString(),
};
// 4. Send response
ctx.set("Content-Type", "application/json");
ctx.send(errorResponse);
// 5. Stop processing
return;
}
// Handle successful responses
};
Error Cases
- 404 Not Found: Send 404 response if no error and no response was sent
- 400 Bad Request: Use
ctx.send(<message>, 400)
for validation errors - 401 Unauthorized: Use
ctx.send(<message>, 401)
withWWW-Authenticate
header - 403 Forbidden: Use
ctx.send(<message>, 403)
for permission issues - 500 Internal Error: Handle unexpected errors with generic messages
Best Practices
- Centralize: Implement error handling in global middleware
- Standardize: Use consistent JSON structure for error responses
- Log Effectively: Include request context in error logs
- Secure: Never leak sensitive information in production
- Use
ctx.send(error, <status code>)
: Prefer it for HTTP-specific errors
Next Steps
- Review the Middleware documentation
- Learn about the Context (
ctx
) Object methods