Skip to content

NestJS HTTP Exceptions

NestJS ships a full set of HttpException subclasses matching common HTTP status codes. This lesson covers when to use each one and how to customize their response body.

The Base HttpException Class

Every built-in exception extends HttpException, which takes a response body (a string or object) and a status code. Throwing any subclass anywhere in your request pipeline, controller, service, guard, pipe, is automatically caught and formatted by Nest's exception layer.

import { NotFoundException } from '@nestjs/common';

throw new NotFoundException('Cat not found');
// equivalent to:
throw new HttpException('Cat not found', 404);

NotFoundException is simply a convenience subclass that hardcodes status 404, both lines above produce an identical response.

Common Built-in Exception Classes

new BadRequestException()     // 400
new UnauthorizedException()   // 401
new ForbiddenException()      // 403
new NotFoundException()       // 404
new ConflictException()       // 409
new UnprocessableEntityException() // 422
new InternalServerErrorException() // 500
  • Each subclass hardcodes the matching HTTP status code so you don't repeat numeric literals.
  • The constructor accepts a string message or a custom object for the response body.
  • Throwing from a service is just as valid as throwing from a controller, the exception layer catches both equally.
  • Prefer the most specific exception available rather than a generic HttpException with a manual status code.

HTTP Exception Reference

The built-in exception classes and when to use them.

Class Status Typical Use
BadRequestException 400 Malformed or invalid input
UnauthorizedException 401 Missing or invalid authentication
ForbiddenException 403 Authenticated but not permitted
NotFoundException 404 Resource does not exist
ConflictException 409 Duplicate or conflicting resource
UnprocessableEntityException 422 Semantically invalid input
InternalServerErrorException 500 Unexpected server-side failure

Customizing the Response Body

Passing an object instead of a string to any HttpException subclass lets you control the exact response shape, useful for adding an error code alongside a human-readable message.

throw new BadRequestException({
  errorCode: 'INVALID_EMAIL',
  message: 'The provided email address is not valid',
});

Choosing the Right Status Code

Picking an accurate status code matters for API consumers building automated retry or error-handling logic. 400 generally means the client sent something malformed; 422 means the request was well-formed but semantically invalid (like a business rule violation); 409 specifically signals a conflicting state.

Common Mistakes

  • Throwing a generic HttpException with a hardcoded status number instead of the matching named subclass.
  • Returning 404 for authorization failures that should really be 403 (or vice versa).
  • Using 400 for every kind of validation failure instead of distinguishing malformed input from semantic violations.
  • Including sensitive internal details in a custom response body meant for public API consumers.

Key Takeaways

  • Built-in exception subclasses hardcode their matching HTTP status code for convenience and clarity.
  • Exceptions can be thrown from controllers, services, guards, or pipes, all are caught the same way.
  • Passing an object instead of a string customizes the full response body.
  • Choosing the most accurate status code improves how well clients can handle errors programmatically.

Pro Tip

Standardize on a small, documented set of custom error codes (like INVALID_EMAIL, RESOURCE_LOCKED) passed inside your exception response bodies, giving API consumers something more precise and stable to branch on than parsing your human-readable message text.