📖 Scenario: You are building a NestJS backend API that needs to handle errors gracefully. Instead of sending raw error messages to clients, you want to map exceptions to friendly HTTP responses.
🎯 Goal: Create a NestJS interceptor called ExceptionMappingInterceptor that catches exceptions thrown by route handlers and maps them to custom error responses.
📋 What You'll Learn
Create an interceptor class named ExceptionMappingInterceptor implementing NestInterceptor.
Use RxJS catchError operator to catch exceptions.
Map exceptions to a custom error object with statusCode and message.
Throw an HttpException with the mapped error.
Apply the interceptor to a sample controller method.
💡 Why This Matters
🌍 Real World
Backend APIs often need to handle errors gracefully and send clear messages to clients. This interceptor helps centralize error handling.
💼 Career
Understanding interceptors and error handling in NestJS is essential for backend developers building robust and maintainable APIs.
Progress0 / 4 steps
1
Create the ExceptionMappingInterceptor class
Create a class called ExceptionMappingInterceptor that implements NestInterceptor. Import Injectable from @nestjs/common. Add the @Injectable() decorator above the class.
NestJS
Hint
Remember to import Injectable, NestInterceptor, ExecutionContext, and CallHandler from @nestjs/common.
2
Add RxJS catchError to intercept method
Inside the intercept method, return next.handle() piped with catchError from rxjs/operators. Import catchError from rxjs/operators and throwError from rxjs.
NestJS
Hint
Use next.handle().pipe(catchError(...)) to catch errors from the route handler.
3
Map exceptions to custom error and throw HttpException
Inside the catchError callback, create a variable mappedError with statusCode set to 500 and message set to 'Internal server error'. Import HttpException from @nestjs/common. Throw a new HttpException with mappedError and mappedError.statusCode using throwError(() => new HttpException(...)).
NestJS
Hint
Use throwError(() => new HttpException(...)) to rethrow the mapped error.
4
Apply the ExceptionMappingInterceptor to a controller method
Create a controller class called AppController with a method getHello that throws an error with message 'Something went wrong'. Import Controller, Get, and UseInterceptors from @nestjs/common. Apply the ExceptionMappingInterceptor to the getHello method using @UseInterceptors(ExceptionMappingInterceptor).
NestJS
Hint
Use @UseInterceptors(ExceptionMappingInterceptor) above the method to apply the interceptor.
Practice
(1/5)
1. What is the main purpose of an ExceptionMappingInterceptor in NestJS?
easy
A. To catch exceptions and transform them into user-friendly responses
B. To log all incoming HTTP requests
C. To validate incoming request data automatically
D. To manage database connections
Solution
Step 1: Understand the role of interceptors
Interceptors in NestJS can modify requests or responses and handle errors.
Step 2: Identify the function of exception mapping
An ExceptionMappingInterceptor specifically catches exceptions and converts them into consistent, user-friendly API responses.
Final Answer:
To catch exceptions and transform them into user-friendly responses -> Option A
5. You want to create an ExceptionMappingInterceptor that converts all QueryFailedError exceptions into BadRequestException with a custom message, but lets other exceptions pass unchanged. Which code snippet correctly implements this behavior?
hard
A. return next.handle().pipe(catchError(err => {
if (err instanceof QueryFailedError) {
return throwError(() => new BadRequestException('Invalid query'));
}
return throwError(() => err);
}));
B. return next.handle().pipe(catchError(err => {
if (err instanceof QueryFailedError) {
throw new BadRequestException('Invalid query');
}
throw err;
}));
C. return next.handle().pipe(catchError(err => {
if (err.name === 'QueryFailedError') {
return new BadRequestException('Invalid query');
}
return err;
}));
D. return next.handle().pipe(catchError(err => {
if (err instanceof BadRequestException) {
return throwError(() => new QueryFailedError());
}
return throwError(() => err);
}));
Solution
Step 1: Check error type and return observable error
The interceptor must check if the error is a QueryFailedError instance and return a new BadRequestException wrapped in throwError.
Step 2: Pass other errors unchanged as observable errors
Other errors must be re-thrown as observable errors using throwError to keep the stream consistent.
Final Answer:
Option A correctly checks error type and returns observable errors properly -> Option A
Quick Check:
Use instanceof + throwError for error mapping [OK]
Hint: Use instanceof and return throwError for mapped and original errors [OK]
Common Mistakes:
Throwing errors directly inside catchError
Returning error objects instead of observable errors
Checking error name string instead of instanceof
Swapping error types incorrectly
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.