NestJS Sentry Integration Module
nest-raven is a module designed to seamlessly integrate Sentry error tracking into applications built with the NestJS framework. It replaces the deprecated `raven` package with the modern `@sentry/node` SDK, providing a robust solution for capturing exceptions. Currently stable at v10.1.0, the package typically releases updates in alignment with major NestJS framework versions, alongside regular dependency maintenance. While it offers a quick starter for common REST/GraphQL error capturing via interceptors and filters, the documentation advises that for large-scale projects requiring deeper Sentry integration beyond basic error handling, developers might consider using this library as a reference to implement a custom solution tailored to their specific needs. Its primary differentiators are its NestJS-native interceptor approach and a clear migration path from older Sentry integration methods.
Common errors
-
Error: Sentry SDK is not initialized, call Sentry.init() first.
cause The `@sentry/node` SDK was not initialized with `Sentry.init()` before the NestJS application started or before an error occurred.fixAdd `Sentry.init({ dsn: process.env.SENTRY_DSN });` to your `main.ts` file at the top, before `NestFactory.create()`. -
Error: Can't resolve '@sentry/node' in 'node_modules/nest-raven/dist'
cause `@sentry/node` is a peer dependency of `nest-raven` but was not installed in your project.fixInstall `@sentry/node`: `npm install @sentry/node` or `yarn add @sentry/node`. -
TypeError: Cannot read properties of undefined (reading 'switchToHttp')
cause This error can occur in a custom `transformer` function if the `context` passed to it is not an HTTP context (e.g., from a GraphQL execution context) and the code assumes `switchToHttp()` is always available without checking.fixSafely check the context type within your transformer: `const http = context.getType() === 'http' ? context.switchToHttp() : null;`
Warnings
- breaking Version 10.0.0 of `nest-raven` requires NestJS v10.0.0 or higher. Ensure your `@nestjs/common` and other core NestJS packages are updated accordingly.
- breaking Version 8.0.0 of `nest-raven` introduced a breaking change by upgrading to NestJS v8. This required corresponding updates in your NestJS application dependencies.
- gotcha The Sentry SDK (`@sentry/node`) must be initialized manually using `Sentry.init()` in your application's `main.ts` file or similar entry point, *before* NestJS application bootstrap. `nest-raven` does not handle this initialization.
- gotcha When `RavenInterceptor` is applied globally using `APP_INTERCEPTOR`, it only captures exceptions from HTTP controllers. It does not provide error capturing for WebSockets (Gateways) due to a limitation in how NestJS applies global interceptors.
- gotcha This module is described as a 'quick starter' and may not be sufficient for large applications requiring deep Sentry integration beyond basic REST/GraphQL error capturing. Custom Sentry integrations may be necessary.
Install
-
npm install nest-raven -
yarn add nest-raven -
pnpm add nest-raven
Imports
- RavenModule
const { RavenModule } = require('nest-raven');import { RavenModule } from 'nest-raven'; - RavenInterceptor
import RavenInterceptor from 'nest-raven';
import { RavenInterceptor } from 'nest-raven'; - APP_INTERCEPTOR
import { APP_INTERCEPTOR } from '@nestjs/core';
Quickstart
import { NestFactory } from '@nestjs/core';
import { Module, NestModule, UseInterceptors, Get, HttpException, Controller } from '@nestjs/common';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { RavenModule, RavenInterceptor } from 'nest-raven';
import * as Sentry from '@sentry/node';
// Initialize Sentry SDK early in your application lifecycle
Sentry.init({
dsn: process.env.SENTRY_DSN ?? 'YOUR_SENTRY_DSN_HERE',
tracesSampleRate: 1.0,
});
@Controller()
class AppController {
@UseInterceptors(new RavenInterceptor({
filters: [
{ type: HttpException, filter: (exception: HttpException) => exception.getStatus() < 500 }
],
// Example transformer to add custom data to Sentry scope
// transformer: (scope, context) => {
// const http = context.getType() === 'http' ? context.switchToHttp() : null;
// if (http) {
// const request = http.getRequest();
// scope.setExtra('customRequestData', { url: request.url, method: request.method });
// }
// return scope;
// }
}))
@Get('/error')
public async triggerError() {
throw new Error('This is a test error to be captured by Sentry!');
}
@Get('/client-error')
public async clientError() {
throw new new HttpException('This is a client error (400 level)', 400);
}
@Get('/server-error')
public async serverError() {
throw new new HttpException('This is a server error (500 level)', 500);
}
}
@Module({
imports: [RavenModule],
controllers: [AppController],
providers: [
{
provide: APP_INTERCEPTOR,
useValue: new RavenInterceptor(), // Global interceptor without filters
},
],
})
export class ApplicationModule {}
async function bootstrap() {
const app = await NestFactory.create(ApplicationModule);
await app.listen(3000);
console.log('Application is running on: http://localhost:3000');
console.log('Visit /error, /client-error, /server-error to trigger errors.');
}
bootstrap();