@nestjs/common#Catch TypeScript Examples

The following examples show how to use @nestjs/common#Catch. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: all-exception.filter.ts    From codeclannigeria-backend with MIT License 6 votes vote down vote up
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
  // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
  catch(exception: unknown, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    const request = ctx.getRequest();

    let status = HttpStatus.INTERNAL_SERVER_ERROR;
    if (exception instanceof HttpException) status = exception.getStatus();
    else Sentry.captureException(exception);

    response.status(status).json({
      statusCode: status,
      timestamp: new Date().toISOString(),
      path: request.url
    });
  }
}
Example #2
Source File: http.filter.ts    From nestjs-starter with MIT License 6 votes vote down vote up
@Catch()
export class HttpExceptionFilter implements ExceptionFilter {
  private readonly logger = new Logger(HttpExceptionFilter.name);

  catch(exception: any, host: ArgumentsHost): void {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    const request = ctx.getRequest();
    const status =
      exception instanceof HttpException
        ? exception.getStatus()
        : HttpStatus.INTERNAL_SERVER_ERROR;
    if (status >= 500) {
      this.logger.error(exception.stack);
    } else {
      this.logger.error(exception.message);
    }

    response.status(status).json({
      statusCode: status,
      timestamp: new Date().toISOString(),
      path: request.url,
    });
  }
}
Example #3
Source File: http-exception.filter.ts    From nestjs-starter with MIT License 6 votes vote down vote up
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(error: any, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const res = ctx.getResponse() as Response;
    const req = ctx.getRequest();
    const statusCode = error.getStatus();
    const stacktrace = error.stack;
    const errorName = error.response.name || error.response.error || error.name;
    const errors = error.response.errors || null;
    const path = req ? req.url : null;

    if (statusCode === HttpStatus.UNAUTHORIZED) {
      if (typeof error.response !== 'string') {
        error.response.message = error.response.message || 'You do not have permission to access this resource';
      }
    }

    const exception = new ApiException(error.response.message, errorName, stacktrace, errors, path, statusCode);
    res.status(statusCode).json(exception);
  }
}
Example #4
Source File: query-failed.filter.ts    From bank-server with MIT License 6 votes vote down vote up
@Catch(QueryFailedError)
export class QueryFailedFilter implements ExceptionFilter {
    constructor(public reflector: Reflector) {}

    catch(exception: any, host: ArgumentsHost) {
        const ctx = host.switchToHttp();
        const response = ctx.getResponse<Response>();

        const errorMessage = ConstraintErrors[exception.constraint];

        const status =
            exception.constraint && exception.constraint.startsWith('UQ')
                ? HttpStatus.CONFLICT
                : HttpStatus.INTERNAL_SERVER_ERROR;

        response.status(status).json({
            statusCode: status,
            error: STATUS_CODES[status],
            message: errorMessage,
        });
    }
}
Example #5
Source File: bad-request.filter.ts    From bank-server with MIT License 6 votes vote down vote up
@Catch(BadRequestException)
export class HttpExceptionFilter implements ExceptionFilter {
    constructor(public reflector: Reflector) {}

    catch(exception: BadRequestException, host: ArgumentsHost) {
        const ctx = host.switchToHttp();
        const response = ctx.getResponse<Response>();
        let statusCode = exception.getStatus();
        const r = <any>exception.getResponse();

        if (_.isArray(r.message) && r.message[0] instanceof ValidationError) {
            statusCode = HttpStatus.UNPROCESSABLE_ENTITY;
            const validationErrors = <ValidationError[]>r.message;
            this._validationFilter(validationErrors);
        }

        r.statusCode = statusCode;
        r.error = STATUS_CODES[statusCode];

        response.status(statusCode).json(r);
    }

    private _validationFilter(validationErrors: ValidationError[]) {
        for (const validationError of validationErrors) {
            for (const [constraintKey, constraint] of Object.entries(
                validationError.constraints,
            )) {
                if (!constraint) {
                    // convert error message to error.fields.{key} syntax for i18n translation
                    validationError.constraints[constraintKey] =
                        'error.fields.' + _.snakeCase(constraintKey);
                }
            }
            if (!_.isEmpty(validationError.children)) {
                this._validationFilter(validationError.children);
            }
        }
    }
}
Example #6
Source File: exception.filter.ts    From nestjs-enlighten with MIT License 6 votes vote down vote up
@Catch()
export class ExceptionFilter extends BaseExceptionFilter {
	private disableEnlighten: boolean
	private theme: string

	constructor(options: EnlightenConstructor = {
		disableEnlighten: false,
		theme: 'theme-light'
	}) {
		super()
		this.disableEnlighten = options.disableEnlighten
		this.theme = options.theme
	}

	catch(exception: any, host: ArgumentsHost) {
		if (host.getType() != 'http') {
			return;
		}
		const request = host.switchToHttp().getRequest()
		const response = host.switchToHttp().getResponse()

		if (this.disableEnlighten === true) {
			response.status(response.statusCode).json(exception.response)
			return
		}

		new ViewCompilerService(request, exception).getCompiledView(this.theme)
			.then(compiledView => {
				response.status(response.statusCode).send(compiledView)
			})
	}
}
Example #7
Source File: http-error.filter.ts    From postgres-nest-react-typescript-boilerplate with GNU General Public License v3.0 6 votes vote down vote up
@Catch()
export class HttpErrorFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    const request = ctx.getRequest();
    const status = exception.getStatus();

    const errorResponse = {
      statusCode: status,
      timestamp: new Date().toLocaleString(),
      path: request.url,
      method: request.method,
      message:
        status !== HttpStatus.INTERNAL_SERVER_ERROR
          ? exception.message || null
          : 'Internal server error',
    };

    if (status === HttpStatus.INTERNAL_SERVER_ERROR) {
      Logger.error(
        `${request.method} ${request.url}`,
        exception.stack,
        'ExceptionFilter',
      );
    } else {
      Logger.error(
        `${request.method} ${request.url}`,
        JSON.stringify(errorResponse),
        'ExceptionFilter',
      );
    }

    response.status(status).json(errorResponse);
  }
}
Example #8
Source File: http-exception.filter.ts    From Phantom with MIT License 6 votes vote down vote up
@Catch()
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    const request = ctx.getRequest();
    const status = exception.getStatus
      ? exception.getStatus()
      : HttpStatus.INTERNAL_SERVER_ERROR;

    const errorResponse = {
      code: status,
      timestamp: new Date().toLocaleDateString(),
      path: request.url,
      method: request.method,
      message:
        status !== HttpStatus.INTERNAL_SERVER_ERROR
          ? exception.message || null
          : 'Internal server error',
    };

    response.status(status).json(errorResponse);
  }
}
Example #9
Source File: all-exception.filter.ts    From life-helper-backend with MIT License 6 votes vote down vote up
/**
 * 全局异常过滤器
 *
 *
 * ## 说明
 *
 * ```markdown
 * 1. 装饰器 `@Catch()` 参数为空表示捕获所有错误。
 * ```
 *
 *
 * ### 处理策略
 *
 * ```markdown
 * 1. 继承自 `HttpException` 的错误,为已知错误,直接返回定义的结果。
 * 2. 非继承自 `HttpException` 的错误,为未知错误,返回默认的错误提示。
 * ```
 */
@Catch()
export class AllExceptionFilter implements ExceptionFilter {
  private readonly logger = new Logger(AllExceptionFilter.name)

  catch(exception: HttpException | Error, host: ArgumentsHost): void {
    const ctx = host.switchToHttp()

    const request = ctx.getRequest<Request>()
    const response = ctx.getResponse<Response>()

    if (exception instanceof HttpException) {
      const status = exception.getStatus()
      const responseContent = exception.getResponse()
      this.logger.verbose(`[${request.method} ${request.url}] 已知错误`)
      response.status(status).json(responseContent)
    } else {
      this.logger.warn(`[${request.method} ${request.url}] 未知错误:${exception}`)
      response.status(HttpStatus.INTERNAL_SERVER_ERROR).json(COMMON_SERVER_ERROR)
    }
  }
}
Example #10
Source File: http-exception.filter.ts    From nest-js-products-api with MIT License 6 votes vote down vote up
@Catch()
export default class HttpExceptionFilter implements ExceptionFilter<Error> {
  catch(exception: Error, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();

    const { message, status } = this.isBusinessException(exception);
    response.status(status).json({
      message,
      statusCode: status,
      timestamp: new Date().toISOString(),
      path: request.url,
    });
  }

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  public isBusinessException(exception: Error): any {
    if (exception instanceof PriceProductLessZeroException) {
      return {
        message: exception.message,
        status: 400,
      };
    }
    Logger.log(exception.stack);
    return {
      message: 'unknown',
      status: 500,
    };
  }
}
Example #11
Source File: error-catch.filter.ts    From erda-ui with GNU Affero General Public License v3.0 6 votes vote down vote up
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
  catch(exception: Error, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    const request = ctx.getRequest();

    const status = exception instanceof HttpException ? exception.getStatus() : HttpStatus.INTERNAL_SERVER_ERROR;

    logger.error('unexpected exception:', exception);

    response.status(status).json({
      statusCode: status,
      timestamp: new Date().toISOString(),
      path: request.url,
    });
  }
}
Example #12
Source File: http-exception.filter.ts    From codeclannigeria-backend with MIT License 6 votes vote down vote up
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
  catch(error: any, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const res = ctx.getResponse() as Response;
    const req = ctx.getRequest();
    const statusCode = error.getStatus();
    const stacktrace =
      configuration().environment === 'production' ? null : error.stack;
    const errorName = error.response.name || error.response.error || error.name;
    const errors = error.response.errors || null;
    const path = req ? req.url : null;

    if (statusCode === HttpStatus.UNAUTHORIZED) {
      if (typeof error.response !== 'string') {
        error.response.message =
          error.response.message ||
          'You do not have permission to access this resource';
      }
    }

    const exception = new ApiException(
      error.response.message,
      errorName,
      stacktrace,
      errors,
      path,
      statusCode
    );
    res.status(statusCode).json(exception);
  }
}
Example #13
Source File: rest-exception.filter.ts    From Cromwell with MIT License 6 votes vote down vote up
@Catch(HttpException)
export class RestExceptionFilter implements NestExceptionFilter {
    public async catch(exception: HttpException, host: ArgumentsHost) {
        const ctx = host.switchToHttp();
        const response = ctx.getResponse<FastifyReply>();
        const request = ctx.getRequest<Request>();
        const status = exception.getStatus();
        const message = exception.message || "Internal error";

        response
            .status(status)
            .send({
                message,
                statusCode: status,
                timestamp: new Date().toISOString(),
                path: request.url,
            });
    }
}
Example #14
Source File: http-exception.filter.ts    From nestjs-crud-prisma with MIT License 6 votes vote down vote up
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const status = exception.getStatus();
    const message: string | object = exception.getResponse();
    response
      .status(status)
      .json(typeof message === 'object' ? { ...message } : { message });
  }
}
Example #15
Source File: http-exception.filter.ts    From aqualink-app with MIT License 6 votes vote down vote up
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  private readonly logger = new Logger(HttpExceptionFilter.name);
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();

    this.logger.error(
      `An error has occurred: ${exception.message}`,
      exception.stack,
    );
    response.status(exception.getStatus()).json(exception.getResponse());
  }
}
Example #16
Source File: github-auth-exception.filter.ts    From amplication with Apache License 2.0 6 votes vote down vote up
@Catch(Error)
export class GithubAuthExceptionFilter implements ExceptionFilter {
  constructor(
    @Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger,
    private readonly configService: ConfigService
  ) {}

  catch(exception: Error, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();

    this.logger.error(exception.message, { request });

    response.redirect(`/login/?error=${encodeURIComponent(exception.message)}`);
  }
}
Example #17
Source File: unauthorized.filter.ts    From aqualink-app with MIT License 6 votes vote down vote up
@Catch(UnauthorizedException)
export class UnauthorizedExceptionFilter implements ExceptionFilter {
  private readonly logger = new Logger(UnauthorizedExceptionFilter.name);
  catch(exception: UnauthorizedException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    const status = exception.getStatus();

    this.logger.error(
      `An error has occurred: ${exception.message}`,
      exception.stack,
    );

    response.status(status).json({
      statusCode: status,
      message: 'You are not allowed to execute this operation.',
    });
  }
}
Example #18
Source File: mongo.exceptions.ts    From uniauth-backend with MIT License 6 votes vote down vote up
@Catch(Error)
export class MongoExceptionFilter implements ExceptionFilter {
  catch(error: any) {
    if (error.name === 'ValidationError') {
      const errors = {};

      Object.keys(error.errors).forEach((key) => {
        errors[key] = error.errors[key].message;
      });
      throw new BadRequestException(errors);
    }
  }
}
Example #19
Source File: nuxtExpress.filter.ts    From nest-nuxt-starter with MIT License 6 votes vote down vote up
@Catch(NotFoundException)
export class NuxtExpressFilter implements ExceptionFilter {
  private readonly nuxt: Nuxt;

  constructor(nuxt: Nuxt) {
    this.nuxt = nuxt;
  }

  public async catch(
    exception: NotFoundException,
    host: ArgumentsHost,
  ): Promise<void> {
    const ctx = host.switchToHttp();
    const res = ctx.getResponse();
    const req = ctx.getRequest();

    if (jsonRequest(req.headers)) {
      const status = exception.getStatus();
      res.status(status).send({
        message: exception.message,
        statusCode: status,
        timestamp: new Date().toISOString(),
        path: req.url,
      });
    } else {
      if (!res.headersSent) {
        await this.nuxt.render(req, res);
      }
    }
  }
}
Example #20
Source File: all-exception.filter.ts    From nestjs-geteventstore with MIT License 6 votes vote down vote up
@Catch()
export class AllExceptionFilter implements ExceptionFilter {
  catch(exception: unknown, host: ArgumentsHost): void {
    console.log('Main exception handler');
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();

    const status = (exception as any).status ?? 500;
    const message = (exception as any).message ?? '';

    response.status(status).json({
      statusCode: status,
      timestamp: new Date().toISOString(),
      path: request.url,
      message,
    });
  }
}
Example #21
Source File: ws-exceptions.filter.ts    From nest-js-boilerplate with MIT License 6 votes vote down vote up
@Catch()
export default class WsExceptionsFilter extends BaseWsExceptionFilter {
  catch(exception: any, host: ArgumentsHost ) {
    const client = host.switchToWs().getClient();

    if (exception.response?.statusCode === 401) {
      client.emit('on-error', {
        message: exception.response.message,
        statusCode: exception.response.statusCode,
      });
      return;
    }

    super.catch(exception, host);
  }
}
Example #22
Source File: nuxtFastify.filter.ts    From nest-nuxt-starter with MIT License 6 votes vote down vote up
@Catch(NotFoundException)
export class NuxtFastifyFilter implements ExceptionFilter {
  private readonly nuxt: Nuxt;

  constructor(nuxt: Nuxt) {
    this.nuxt = nuxt;
  }

  public async catch(
    exception: NotFoundException,
    host: ArgumentsHost,
  ): Promise<void> {
    const ctx = host.switchToHttp();
    const res = ctx.getResponse();
    const req = ctx.getRequest();

    if (jsonRequest(req.raw.headers)) {
      const status = exception.getStatus();
      res.status(status).send({
        message: exception.message,
        statusCode: status,
        timestamp: new Date().toISOString(),
        path: req.url,
      });
    } else {
      const sharedReq = req.raw;
      const sharedRes = res.raw;

      sharedReq.fastifyRequest = req;
      sharedRes.fastifyReply = res;

      if (!res.headersSent) {
        await this.nuxt.render(sharedReq, sharedRes);
      }
    }
  }
}
Example #23
Source File: all-exceptions.filter.ts    From nest-js-boilerplate with MIT License 6 votes vote down vote up
@Catch()
export default class AllExceptionsFilter implements ExceptionFilter {
  catch(exception: any, host: ArgumentsHost) {
    const ctx: HttpArgumentsHost = host.switchToHttp();
    const res = ctx.getResponse<ExpressResponse>();
    const exceptionResponse: null | ExceptionResponse = exception.getResponse
      ? (exception.getResponse() as ExceptionResponse)
      : null;
    const status: number = exception.getStatus ? exception.getStatus() : 500;

    const mongodbCodes = {
      bulkWriteError: 11000, // a duplicate error code in mongoose
    };

    if (exception.code === mongodbCodes.bulkWriteError) {
      return res.status(HttpStatus.CONFLICT).json(
        new Error({
          source: { pointer: '/data/attributes/email' },
          title: 'Duplicate key',
          detail: exception.message,
        }),
      );
    }

    if (exception.response?.errorType === 'ValidationError') {
      return res.status(HttpStatus.BAD_REQUEST).json(
        new Error(exceptionResponse ? exceptionResponse.errors : {}),
      );
    }

    return res.status(status).json(new Error({
      title: exceptionResponse?.error,
      detail: exception?.message,
    }));
  }
}
Example #24
Source File: all-exceptions.filter.ts    From nest-js-boilerplate with MIT License 6 votes vote down vote up
@Catch()
export default class AllExceptionsFilter implements ExceptionFilter {
  catch(exception: any, host: ArgumentsHost) {
    const ctx: HttpArgumentsHost = host.switchToHttp();
    const res = ctx.getResponse<ExpressResponse>();
    const exceptionMessage: string | null = exception.message || null;
    const exceptionResponse: null | ExceptionResponse = exception.getResponse
      ? (exception.getResponse() as ExceptionResponse)
      : null;
    const status: number = exception.getStatus ? exception.getStatus() : 500;

    const mysqlCodes = {
      duplicateError: 'ER_DUP_ENTRY',
    };

    if (exception.code === mysqlCodes.duplicateError) {
      return res
        .status(HttpStatus.CONFLICT)
        .json({ message: exceptionMessage, error: exceptionResponse });
    }

    return res.status(status).json({
      message: exceptionMessage,
      error: exceptionResponse,
    });
  }
}
Example #25
Source File: all-exceptions.filter.ts    From nest-js-boilerplate with MIT License 6 votes vote down vote up
@Catch()
export default class AllExceptionsFilter implements ExceptionFilter {
  catch(exception: any, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const res = ctx.getResponse<Response>();

    const mongodbCodes = {
      bulkWriteError: 11000,
    };

    if (exception.code === mongodbCodes.bulkWriteError) {
      return res.status(HttpStatus.CONFLICT).json({
        message:
          'Any message which should help the user to resolve the conflict',
      });
    }

    if (
      exception instanceof NotFoundException ||
      exception instanceof UnauthorizedException ||
      exception instanceof BadRequestException ||
      exception.code === 'ValidationException'
    ) {
      return res.redirect('/v1/auth/sign-up'); // here you can specify rendering your page
    }
    return res
      .status(HttpStatus.INTERNAL_SERVER_ERROR)
      .json({ message: 'Something is broken' });
  }
}
Example #26
Source File: all-exception.filter.ts    From nest-js-boilerplate with MIT License 6 votes vote down vote up
@Catch()
export default class AllExceptionsFilter implements ExceptionFilter {
  catch(exception: any, host: ArgumentsHost) {
    const ctx: HttpArgumentsHost = host.switchToHttp();
    const res = ctx.getResponse<ExpressResponse>();
    const exceptionResponse: null | ExceptionResponse = exception.getResponse
      ? (exception.getResponse() as ExceptionResponse)
      : null;
    const status: number = exception.getStatus ? exception.getStatus() : 500;

    const mongodbCodes = {
      bulkWriteError: 11000, // a duplicate error code in mongoose
    };

    if (exception.code === mongodbCodes.bulkWriteError) {
      return res.status(HttpStatus.CONFLICT).json({
        message: exceptionResponse?.message,
        error: exceptionResponse?.error,
      });
    }

    return res.status(status).json({
      message: exceptionResponse?.message,
      error: exceptionResponse?.error,
    });
  }
}
Example #27
Source File: forbidden-exception.filter.ts    From nestjs-mercurius with MIT License 5 votes vote down vote up
@Catch(ForbiddenException)
export class ForbiddenExceptionFilter implements ExceptionFilter {
  catch(exception: any, host: ArgumentsHost): any {
    const gqlHost = GqlArgumentsHost.create(host);

    throw exception;
  }
}
Example #28
Source File: NestHttpExceptionFilter.ts    From typescript-clean-architecture with MIT License 5 votes vote down vote up
@Catch()
export class NestHttpExceptionFilter implements ExceptionFilter {
  
  public catch(error: Error, host: ArgumentsHost): void {
    const request: Request = host.switchToHttp().getRequest();
    const response: Response = host.switchToHttp().getResponse<Response>();
    
    let errorResponse: CoreApiResponse<unknown> = CoreApiResponse.error(Code.INTERNAL_ERROR.code, error.message);
  
    errorResponse = this.handleNestError(error, errorResponse);
    errorResponse = this.handleCoreException(error, errorResponse);
    
    if (ApiServerConfig.LOG_ENABLE) {
      const message: string =
        `Method: ${request.method}; ` +
        `Path: ${request.path}; `+
        `Error: ${errorResponse.message}`;
  
      Logger.error(message);
    }
    
    response.json(errorResponse);
  }
  
  private handleNestError(error: Error, errorResponse: CoreApiResponse<unknown>): CoreApiResponse<unknown> {
    if (error instanceof HttpException) {
      errorResponse = CoreApiResponse.error(error.getStatus(), error.message, null);
    }
    if (error instanceof UnauthorizedException) {
      errorResponse = CoreApiResponse.error(Code.UNAUTHORIZED_ERROR.code, Code.UNAUTHORIZED_ERROR.message, null);
    }
    
    return errorResponse;
  }
  
  private handleCoreException(error: Error, errorResponse: CoreApiResponse<unknown>): CoreApiResponse<unknown> {
    if (error instanceof Exception) {
      errorResponse = CoreApiResponse.error(error.code, error.message, error.data);
    }
    
    return errorResponse;
  }

}
Example #29
Source File: all-exceptions.filter.ts    From nestjs-starter-rest-api with MIT License 5 votes vote down vote up
@Catch()
export class AllExceptionsFilter<T> implements ExceptionFilter {
  /** set logger context */
  constructor(
    private config: ConfigService,
    private readonly logger: AppLogger,
  ) {
    this.logger.setContext(AllExceptionsFilter.name);
  }

  catch(exception: T, host: ArgumentsHost): any {
    const ctx = host.switchToHttp();
    const req: Request = ctx.getRequest<Request>();
    const res: Response = ctx.getResponse<Response>();

    const path = req.url;
    const timestamp = new Date().toISOString();
    const requestId = req.headers[REQUEST_ID_TOKEN_HEADER];
    const requestContext = createRequestContext(req);

    let stack: any;
    let statusCode: HttpStatus;
    let errorName: string;
    let message: string;
    let details: string | Record<string, any>;
    // TODO : Based on language value in header, return a localized message.
    const acceptedLanguage = 'ja';
    let localizedMessage: string;

    // TODO : Refactor the below cases into a switch case and tidy up error response creation.
    if (exception instanceof BaseApiException) {
      statusCode = exception.getStatus();
      errorName = exception.constructor.name;
      message = exception.message;
      localizedMessage = exception.localizedMessage[acceptedLanguage];
      details = exception.details || exception.getResponse();
    } else if (exception instanceof HttpException) {
      statusCode = exception.getStatus();
      errorName = exception.constructor.name;
      message = exception.message;
      details = exception.getResponse();
    } else if (exception instanceof Error) {
      errorName = exception.constructor.name;
      message = exception.message;
      stack = exception.stack;
    }

    // Set to internal server error in case it did not match above categories.
    statusCode = statusCode || HttpStatus.INTERNAL_SERVER_ERROR;
    errorName = errorName || 'InternalException';
    message = message || 'Internal server error';

    // NOTE: For reference, please check https://cloud.google.com/apis/design/errors
    const error = {
      statusCode,
      message,
      localizedMessage,
      errorName,
      details,
      // Additional meta added by us.
      path,
      requestId,
      timestamp,
    };
    this.logger.warn(requestContext, error.message, {
      error,
      stack,
    });

    // Suppress original internal server error details in prod mode
    const isProMood = this.config.get<string>('env') !== 'development';
    if (isProMood && statusCode === HttpStatus.INTERNAL_SERVER_ERROR) {
      error.message = 'Internal server error';
    }

    res.status(statusCode).json({ error });
  }
}