NestJS exception filter that sends only 5xx errors to Sentry. Eliminates 4xx noise, preserves rich request context, handles HTTP + GraphQL.
The default @sentry/nestjs integration captures every exception — including 400 Bad Request, 401 Unauthorized, 404 Not Found. These are expected user errors that flood your Sentry dashboard and burn your error quota.
SmartSentryFilter catches all NestJS exceptions. It checks the HTTP status: if it's in the ignored set (all 4xx by default), it sends the response normally without touching Sentry. Only 5xx (unexpected server errors) get captured. For GraphQL, it unwraps GraphQLError.originalError before deciding.
npm install @zipteams/sentry-filterSentry must already be initialized in your app (via Sentry.init()) before this filter runs.
// app.module.ts
import { SmartSentryFilterModule } from '@zipteams/sentry-filter';
@Module({
imports: [
SmartSentryFilterModule.forRoot({
internalErrorResponse: { code: 500, message: 'Something went wrong' },
}),
],
})
export class AppModule {}// main.ts
import { SmartSentryFilter } from '@zipteams/sentry-filter';
app.useGlobalFilters(new SmartSentryFilter());| Option | Type | Default | Description |
|---|---|---|---|
ignoredStatuses |
number[] |
[400,401,403,404,405,409,422,429] |
HTTP status codes NOT sent to Sentry |
internalErrorResponse |
Record<string, unknown> |
{ code: 500, message: 'Internal server error' } |
Response body for unhandled 500 errors |
captureBody |
boolean |
true |
Include request body in Sentry context |
import { SmartSentryFilterModule, DEFAULT_IGNORED_STATUSES } from '@zipteams/sentry-filter';
SmartSentryFilterModule.forRoot({
// Also ignore 503 (e.g., during maintenance)
ignoredStatuses: [...DEFAULT_IGNORED_STATUSES, 503],
})Works automatically. When the execution context is graphql, the filter:
- Unwraps
GraphQLError.originalErrorto get the real exception - Checks its status (same ignore logic)
- Re-throws the
GraphQLError(required for GQL error propagation)
No additional configuration needed. graphql and @nestjs/graphql are optional peer dependencies — if they are not installed, the filter operates in HTTP-only mode.
For captured exceptions, the filter attaches:
http.status_codetag- Request context: method, URL, headers, query params, path params, body (unless
captureBody: false), IP, user-agent
This package requires Sentry to be initialized before the filter runs:
// instrument.ts (loaded before app bootstrap)
import * as Sentry from '@sentry/nestjs';
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.NODE_ENV,
});The filter is compatible with both adapters. It calls response.status(n).send(body) (Fastify pattern) and falls back to response.status(n).json(body) (Express pattern) automatically.
MIT