Error handling in Nest service layer

error handlingexceptionsonion-architecturetypescript

I would like to create a REST API with NestJs. But I want to add GraphQL as another top level layer later on. So for the start I have the basic layers controller, service and TypeORM repository. Let's assume you want to update a user's username by id. The controller route could be

PATCH /users/:id/username

Two problems might come up in the service or repository layer:

  • The user id might not exist
  • The username exists already

The basic flow of this operation would be

  • Fetch the user by id
  • Handle error if the user does not exist
  • Check if the username exists already
  • Handle error if the username exists already
  • Update the user's username

I'm thinking about how I should handle those errors. I could throw exceptions immediately based on this concept

https://en.wikipedia.org/wiki/Fail-fast

NestJs provides some out of the box exceptions I can use

https://docs.nestjs.com/exception-filters#built-in-http-exceptions

The problem is that I don't think I should throw HTTP exceptions in my service layer. They should be thrown in my controller logic. So what is a common approach for those errors?

  • Should I just return undefined instead of an updated user? The controller wouldn't know which part failed.
  • Should I create my own exceptions extending Error and throw them?
  • Due to the fact exceptions come with low performance should the return type of the function be something like <User | NotFoundError | ConflictError>?

Best Answer

You are correct to say you should not throw HTTP specific exceptions in the service layer. The service layer should not have any knowledge of http things.

Most server frameworks have a top level exception handler and an error handling middleware. That top level exception handler could catch any exceptions not handled by your code and return 500 Internal server error.

Usually you can customize that and say okay if it's this language level exception, use this http response. I don't know the framework you are using, as an example in asp.net, when we throw (System.Collections.Generic) KeyNotFoundException then on the top level we return 404. It's not perfect, but it better than directly coupling the two.

Look here: https://docs.nestjs.com/exception-filters