Open source

PMQ.ErrorHandling

level applied-in-production

1,149 downloads · the largest of the suite · repository

Centralized error handling in ASP.NET Core: exception filter, notification mapping, model state validation and a standardized response.

The problem

Each API answers errors in its own way. One returns a string, another an object with message, another the whole stack trace in production. Whoever integrates has to handle each one differently, and the consumer’s log becomes useless.

The decision: adopt a standard instead of inventing a format

The response follows RFC 9457, the problem details specification: type, title, status, detail, instance, plus an extension for field errors. A client that knows the standard already knows how to read it, and there is no document to maintain explaining a homemade format.

The mapping that closes the suite’s loop

The notification category becomes the HTTP code. This is where the decision made in the domain, three layers back, reaches the API consumer without anyone translating in the middle:

NotificationType when firstNotificationType == NotificationType.NotFound
    => StatusCodes.Status404NotFound,
NotificationType when firstNotificationType == NotificationType.AccessDenied
    => StatusCodes.Status403Forbidden,
NotificationType when firstNotificationType == NotificationType.InconsistentState
    => StatusCodes.Status409Conflict,
NotificationType when firstNotificationType == NotificationType.BusinessRule
    => StatusCodes.Status422UnprocessableEntity,
NotificationType when firstNotificationType == NotificationType.Validation
    => StatusCodes.Status400BadRequest,
_   => StatusCodes.Status422UnprocessableEntity

Two choices I stand by in that excerpt:

422 for business rules, 400 for validation. The distinction is real and almost always ignored: 400 is “the request is malformed”, 422 is “the request is well formed and I refuse to process it”. A client that receives 400 tries to fix the format; one that receives 422 knows the format is right and the problem is the rule.

The _ falls to 422, not 500. An unknown category is, by definition, a rule the library does not know, and not a server failure. Falling to 500 would turn a new business rule into an infrastructure alarm.

Pablo Mickael Quevedo Senior Software Engineer · Novo Hamburgo, Brazil