Production error handling for Express APIs — error middleware, async wrappers,
89
86%
Does it follow best practices?
Impact
97%
2.02xAverage score across 4 eval scenarios
Passed
No known issues
{
"context": "Tests whether the agent proactively adds production-grade error handling (global error middleware, async error catching, structured error responses, no stack trace leaks, 404 handler, graceful shutdown) when building a standard Express CRUD API that does not mention error handling in the requirements.",
"type": "weighted_checklist",
"checklist": [
{
"name": "Global error middleware",
"description": "A centralized error-handling middleware with the Express 4-argument signature (err, req, res, next) is defined and registered as the last app.use() call, after all routes",
"max_score": 15
},
{
"name": "Async error safety",
"description": "All async route handlers are protected against unhandled promise rejections -- either wrapped with an asyncHandler utility that calls .catch(next), or using express-async-errors, or using try/catch with next(err). No bare async (req, res) => {} handlers.",
"max_score": 15
},
{
"name": "Structured error response format",
"description": "Error responses use a consistent object shape with at least a code/type field and a message field (e.g. { error: { code, message } } or { error: { type, message } }). The format is the same across all error cases -- not a mix of { error: 'string' }, { message: '...' }, and other shapes.",
"max_score": 12
},
{
"name": "No stack trace leaks",
"description": "Error responses for unexpected/internal errors return a generic safe message (e.g. 'Internal server error') -- no stack traces, raw library error messages, or internal file paths are included in response bodies",
"max_score": 12
},
{
"name": "Custom error classes",
"description": "Custom error classes (e.g. AppError, NotFoundError, ValidationError) with status codes are defined so routes throw typed errors rather than using inline res.status().json() for error cases",
"max_score": 10
},
{
"name": "404 catch-all handler",
"description": "A catch-all handler is registered after all routes that returns a proper JSON 404 response for unmatched endpoints, instead of Express's default HTML error",
"max_score": 8
},
{
"name": "Graceful shutdown",
"description": "The server handles SIGTERM and/or SIGINT signals by calling server.close() to drain in-flight requests before exiting",
"max_score": 8
},
{
"name": "Appropriate status codes",
"description": "Different error types return semantically correct HTTP status codes: 400 for validation errors, 404 for not-found, 409 for duplicate ISBN conflicts, 500 for unexpected errors -- not all errors mapped to the same code",
"max_score": 10
},
{
"name": "CRUD endpoints functional",
"description": "All five CRUD endpoints are implemented and return appropriate success status codes (200 for reads, 201 for creation, 204 or 200 for delete)",
"max_score": 10
}
]
}