blog bg

May 26, 2025

Understanding Global Exception Filters in NestJS — The Right Way (And the “It Still Works” Way)

Share what you learn in this blog to prepare for your interview, create your forever-free profile now, and explore how to monetize your valuable knowledge.

Understanding Global Exception Filters in NestJS' The Right Way (And the It Still Works Way)

 

When working with NestJS, managing errors consistently across your application is a must. Exception filters allow you to intercept and format errors before they're returned to the client.

 

Today, I want to share something interesting I learned while implementing global exception filters, including a common pattern that works but isn't always recommended, and the preferred approach using NestJS's dependency injection system.

 

 

What Are Exception Filters in NestJS?

Exception filters in NestJS let you handle thrown errors in a structured and reusable way. For example, instead of showing a stack trace, you could return a clean JSON error like

 

{
  "statusCode": 404,
  "success": false,
  "message": "Resource not found"
}

 

 

Applying Filters: Local vs Global

NestJS lets you apply exception filters:

  • Locally: On a specific controller or route
  • Globally: Across the entire application

 

Let's focus on global filters because they're powerful but a bit tricky.

 

Global Filters via useGlobalFilters() (Manual Injection)

This is how I initially set up my global filters:

import { NestFactory } from "@nestjs/core"
import { AppModule } from "./app.module"
import { GlobalExceptionFilters } from "./exceptions/global.exception"
import { LogService } from "./log/log.service"

async function bootstrap() {
  const app = await NestFactory.create(AppModule)

  const logService = app.get(LogService)

  // Register filters manually
  app.useGlobalFilters(new GlobalExceptionFilters(logService))
  await app.listen(3000)
}
bootstrap()

 

Here, I manually inject LogService using app.get(LogService) before passing it to the filters. This works because I'm creating the filter instances myself and not relying on NestJS to inject them.

 

Pros:

  • Quick to set up
  • Gives you full control over instantiation

 

Cons:

  • Not ideal for large-scale apps
  • Filters won't work in microservices or WebSockets
  • Doesn't integrate well with Nest's lifecycle or testing tools

 

The Recommended Way: Registering with APP_FILTER

If your filter needs to use injected services like LogService, the preferred and scalable way is to register it in the module like this:

 

@Module({
  providers: [
    {
      provide: APP_FILTER,
      useClass: GlobalExceptionFilters,
    },
  ],
})
export class AppModule {}

 

This way, NestJS takes care of creating and injecting your filter and its dependencies properly.

 

Pros:

  • Works across HTTP, WebSocket, and microservices
  • Fully integrated into NestJS' Dependency Injection system
  • Cleaner and more scalable
  •  

Cons:

  • Slightly more setup required
  • Might feel less flexible if you're used to full control

 

Key Differences at a Glance

Approach

Can Inject Services?

Microservices Support

Recommended?

useGlobalFilters(new ...) + app.get(...) Yes (manual)Not fullyNot ideal for scale
APP_FILTER in a ModuleYes (automatic)YesYes

 

 

 

 

 

 

 

Final Thoughts

If you're building a quick MVP or small API, manually registering your filters via useGlobalFilters() might be good enough.

 

But if you're building a scalable, maintainable application, especially one that uses WebSockets or microservices, using APP_FILTER is the right choice.

 

Pro Tip:

If you need multiple global filters, register them all in your providers array:

providers: [
  {
    provide: APP_FILTER,
    useClass: GlobalExceptionFilters,
  },
  {
    provide: APP_FILTER,
    useClass: HttpExceptionFilter,
  },
]

 

I hope this helps someone avoid the confusion I ran into. If you found this helpful or have a better pattern, feel free to reach out or drop a comment.

 

Happy coding! 

Sample code: https://github.com/Intuneteq/nestjs-global-filters

139 views

Please Login to create a Question