CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl-labs/express-error-handling

Production error handling for Express APIs — error middleware, async wrappers,

89

2.02x
Quality

86%

Does it follow best practices?

Impact

97%

2.02x

Average score across 4 eval scenarios

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

criteria.jsonevals/scenario-3/

{
  "context": "Tests whether the agent proactively adds production error handling patterns (global error middleware, async safety, structured responses, no leaks) when building a task management CRUD API. The task does not mention error handling -- criteria check whether the agent adds it from day one.",
  "type": "weighted_checklist",
  "checklist": [
    {
      "name": "Global error middleware",
      "description": "A centralized error-handling middleware with (err, req, res, next) signature is defined and registered after all routes",
      "max_score": 14
    },
    {
      "name": "Async error safety",
      "description": "All async route handlers are protected -- wrapped with asyncHandler, try/catch forwarding to next(), or express-async-errors. No bare async handlers.",
      "max_score": 14
    },
    {
      "name": "Structured error responses",
      "description": "All error responses use a consistent object shape with code and message fields. No mix of { error: 'string' } and { message: 'string' } across different routes.",
      "max_score": 12
    },
    {
      "name": "No stack trace leaks",
      "description": "Internal/unexpected errors return a generic safe message -- no stack traces or internal details in the response",
      "max_score": 10
    },
    {
      "name": "Typed error classes",
      "description": "Custom error classes or a base AppError with status codes is used -- routes throw typed errors rather than inline res.status().json()",
      "max_score": 10
    },
    {
      "name": "Validation errors",
      "description": "Validation failures (missing title, invalid status enum, bad email format, title too long, invalid status transition) return 400 with clear messages identifying what was wrong",
      "max_score": 10
    },
    {
      "name": "Not-found handling",
      "description": "Accessing a non-existent task by ID returns 404, not 500 or 200 with an error message in the body",
      "max_score": 8
    },
    {
      "name": "404 catch-all",
      "description": "A catch-all for unmatched routes returns a JSON 404 response",
      "max_score": 7
    },
    {
      "name": "Graceful shutdown",
      "description": "SIGTERM/SIGINT signal handlers with server.close() are implemented",
      "max_score": 7
    },
    {
      "name": "CRUD endpoints functional",
      "description": "All five CRUD endpoints are implemented with appropriate status codes and the status filter query param works",
      "max_score": 8
    }
  ]
}

evals

tile.json