JCC Express

Error Handling

Introduction

JCC Express MVC registers HTTP error handling after routes are built (jcc-express-mvc/lib/Server/index.tshttpErrors). Two pieces from AppErrorHandler matter in order:

  1. errorRoutesHandler — a normal Express handler for requests that never matched a route (404).
  2. handler — Express’s four-argument error middleware (err, req, res, next), which receives failures passed to next(error) or thrown from async code that the router wraps.

Route actions are executed inside asyncHandler and a try / catch so rejected promises and synchronous throws from controller code are forwarded to that error middleware (jcc-express-mvc/lib/Routes/RouteBuilder.ts, jcc-express-mvc/lib/util/index.ts).


404 — no matching route

When no route matches the request, the stack falls through to AppErrorHandler.errorRoutesHandler, which responds with pageNotFound.html from the framework’s Error/public assets at status 404.


Application error middleware (AppErrorHandler.handler)

The handler inspects err in a fixed order (jcc-express-mvc/lib/Error/AppErrorHandler.ts).

AuthorizationException

Thrown when a FormRequest subclass’s authorize() returns true (meaning “not allowed” in this framework’s convention). Response:

  • If req.expectsJson() and the request is not Inertia: 403 JSON { message }.
  • Otherwise: flash key error with message "Forbidden", status 403, redirectBack() (see Response.md).

Validation failures (ValidationException or err.type === VALIDATION_ERROR)

Covers ValidationException from Validator.validate and any error object whose type equals the VALIDATION_ERROR constant (jcc-express-mvc/lib/Error/Constants/error.ts).

  • JSON (expects JSON, not Inertia): 422 with { errors: err.message }. On ValidationException, err.message is actually the flattened field → message map built in ValidationException-v2 (first message per field).
  • Web: 422 redirectBack(). If the error is a ValidationException with errors, VALIDATION_ERROR is flashed again for templates (validation already flashes in Validator.validate; the handler may duplicate that flash).

Details of validation and flashes are in Validation.md, Request.md, and Session.md.

Blade / view engine errors (DEFAULT_ENGINE_ERROR)

Errors tagged with err.type === DEFAULT_ENGINE_ERROR return 500 JSON { errors: err.message }.

Everything else (generic server errors)

Non-matching errors go through stack parsing and APP_DEBUG:

  • APP_DEBUG "true" (string from config): DisplayError.show renders an HTML page with a source snippet around the reported file/line, or 500 JSON with stack and error when the client expects JSON (jcc-express-mvc/lib/Error/DisplayErrorCode.ts).
  • Otherwise: 500 static 500.html from the framework Error/public folder.

Propagating errors from your code

The framework is built with a controller-based architecture similar to Laravel. Rejections and synchronous throws from controller actions are already wired through asyncHandler and the inner catch in registerRoute, so in most cases a simple throw or an await on a failing promise is enough — the error reaches AppErrorHandler without extra boilerplate.

If you prefer explicit control, use try / catch and forward with next(error):

TypeScript

Calling next(error) skips the remaining middleware stack and jumps straight to the error middleware where AppErrorHandler takes over.

Middleware — The same pattern applies: call next(err) with an Error (or subclass) to forward the failure.

Manual JSON errors — For full control over the response, you can return res.status(n).json(...) directly inside a route and never call next.


Helper types and exceptions

AppError (jcc-express-mvc/lib/Error/AppError.ts) — Error subclass with optional type and cause; useful when you want a stable err.type for future branching (today AppErrorHandler only treats VALIDATION_ERROR and DEFAULT_ENGINE_ERROR by type, not AppError specifically).

Other exported errors (for example SocialiteAuthError, MissMatchTokenException) follow normal Error handling unless you map them in custom middleware or extend AppErrorHandler.

Constants under jcc-express-mvc/lib/Error/Constants/error.ts are mostly internal labels for subsystems; the global HTTP behavior above is driven by AppErrorHandler plus VALIDATION_ERROR / DEFAULT_ENGINE_ERROR.


Process-level rejections

unhandledRejection on the process is logged in Server.server; it does not automatically send an HTTP response. Prefer handling failures inside the request pipeline so clients get a proper status and body.


Summary

  • 404 — unmatched routes → framework pageNotFound.html.
  • 403 — AuthorizationException → JSON or flash + redirectBack.
  • 422 — validation-style errors → JSON errors or redirectBack with flashes.
  • 500 — debug HTML/JSON snippet when APP_DEBUG is on, otherwise 500.html.
  • Forward errors with next(err) in middleware; route throw / async failures are already passed to next by the route wrapper.