Skip to Content
Handling Error Documentation

Handling Error Documentation

This documentation explains the features and usage of Exception Filter Module: Located at src/app/filters

Overview

The error handling system provides comprehensive exception management using NestJS’s exception filter mechanism. All errors are transformed into standardized HTTP responses with proper formatting, internationalization, and monitoring integration.

Table of Contents

Exception Filters

Complete NestJS Boilerplate uses 4 specialized exception filters registered globally in hierarchical order:

  1. AppValidationImportFilter - Handles FileImportException
  2. AppValidationFilter - Handles RequestValidationException
  3. AppHttpFilter - Handles HttpException
  4. AppGeneralFilter - Catches all unhandled exceptions

Processing flow:

Exception thrown Match specific filter? (validation import/request, HTTP) ↓ No AppGeneralFilter (fallback) Standardized error response + Sentry (if applicable)

Common behavior:

  • Extract metadata from request (language, version, requestId, correlationId)
  • Generate timestamp and timezone information
  • Resolve localized error message using Message System
  • Set response headers
  • Format into ResponseErrorDto
  • Send to Sentry (conditions vary by filter)

Error Response Structure

All errors are formatted into ResponseErrorDto:

{ "statusCode": number, // Custom status code (not HTTP status) "message": string, // Localized error message "metadata": { ... }, // Request/response metadata "errors": [ ... ], // Optional: validation errors "data": { ... } // Optional: additional error context }

Field descriptions:

FieldTypeRequiredDescription
statusCodenumberYesCustom status code for error identification
messagestringYesLocalized message from Message System
metadataResponseMetadataDtoYesRequest/response metadata
errorsarrayNoValidation error details (validation exceptions only)
dataunknownNoAdditional error context (custom exceptions only)

Response Metadata

ResponseMetadataDto provides contextual information:

{ "language": "en", "timestamp": 1660190937231, "timezone": "Asia/Jakarta", "path": "/api/v1/users", "version": "1", "repoVersion": "1.0.0", "requestId": "550e8400-e29b-41d4-a716-446655440000", "correlationId": "6ba7b810-9dad-11d1-80b4-00c04fd430c8" }

Field sources:

FieldSourceFallback
languagerequest.__languageConfig message.language
timestampHelperService.dateGetTimestamp()-
timezoneHelperService.dateGetZone()-
pathrequest.path-
versionrequest.__versionConfig app.urlVersion.version
repoVersionConfig app.version-
requestIdrequest.id-
correlationIdrequest.correlationId-

Response Headers

All filters set these headers automatically:

x-custom-lang: en x-timestamp: 1660190937231 x-timezone: Asia/Jakarta x-version: 1 x-repo-version: 1.0.0 x-request-id: 550e8400-e29b-41d4-a716-446655440000 x-correlation-id: 6ba7b810-9dad-11d1-80b4-00c04fd430c8

Exception Filters

AppGeneralFilter

Location: src/app/filters/app.general.filter.ts

Catches: @Catch() - all unhandled exceptions

Use case: Fallback for unexpected errors (database crashes, unhandled promise rejections, runtime errors)

Behavior:

  • Always returns HTTP 500
  • Uses message path http.500
  • Sends all exceptions to Sentry

Response example:

{ "statusCode": 500, "message": "Internal Server Error", "metadata": { ... } }

AppHttpFilter

Location: src/app/filters/app.http.filter.ts

Catches: @Catch(HttpException) - all HTTP exceptions

Use case: Standard and custom HTTP exceptions from application code

Path validation: Redirects invalid paths (not starting with globalPrefix or docPrefix) to {globalPrefix}/public/hello with HTTP 308

Custom exception support: Extracts custom properties if exception response implements IAppException:

interface IAppException<T = unknown> { statusCode: number; // Custom status code message: string; // Message path for i18n messageProperties?: object; // Variables for message interpolation data?: T; // Additional error context metadata?: object; // Additional metadata to merge }

Sentry integration: Only sends exceptions with HTTP status ≥ 500

Response example (standard):

{ "statusCode": 404, "message": "Not Found", "metadata": { ... } }

Response example (custom):

{ "statusCode": 5100, "message": "User status active is invalid", "data": { "userId": "123" }, "metadata": { ... } }

AppValidationFilter

Location: src/app/filters/app.validation.filter.ts

Catches: @Catch(RequestValidationException) - request validation errors

Use case: Request body, query parameters, and path parameters validation failures using [class-validator][ref-class-validator]

Behavior:

  • Formats field-specific validation errors
  • Uses MessageService.setValidationMessage()
  • Does not send to Sentry

Response example:

{ "statusCode": 422, "message": "Validation error", "errors": [ { "key": "isEmail", "property": "email", "message": "Email must be a valid email address" } ], "metadata": { ... } }

See Request Validation for details.

AppValidationImportFilter

Location: src/app/filters/app.validation-import.filter.ts

Catches: @Catch(FileImportException) - file import validation errors

Use case: CSV file import validation failures using [class-validator][ref-class-validator]

Behavior:

  • Formats row-level validation errors
  • Uses MessageService.setValidationImportMessage()
  • Does not send to Sentry

Response example:

{ "statusCode": 422, "message": "File import validation failed", "errors": [ { "row": 2, "errors": [ { "key": "isEmail", "property": "email", "message": "Email must be a valid email address" } ] } ], "metadata": { ... } }

See Request Validation for details.

Usage

Error with Default HTTP Exception

For standard HTTP errors:

throw new NotFoundException(); // HTTP 404, statusCode: 404, message: "Not Found"

See [NestJS Exception Filters][ref-nestjs-exception-filters] for available exceptions.

Error with Message Properties

Use message properties for dynamic message interpolation:

throw new BadRequestException({ statusCode: EnumUserStatus_CODE_ERROR.statusInvalid, message: 'user.error.statusInvalid', messageProperties: { status: user.status.toLowerCase(), }, });

Message file (en/user.json):

{ "error": { "statusInvalid": "User status {status} is invalid" } }

Response:

{ "statusCode": 5100, "message": "User status active is invalid", "metadata": { ... } }

Error with Additional Data

Add contextual data to help debugging:

throw new BadRequestException({ statusCode: EnumUserStatus_CODE_ERROR.statusInvalid, message: 'user.error.statusInvalid', messageProperties: { status: user.status.toLowerCase(), }, data: { userId: user._id, currentStatus: user.status, allowedStatuses: ['active', 'inactive'], }, });

Response:

{ "statusCode": 5100, "message": "User status active is invalid", "data": { "userId": "507f1f77bcf86cd799439011", "currentStatus": "active", "allowedStatuses": ["active", "inactive"] }, "metadata": { ... } }
Last updated on