typescript 40 lines · 6 steps

Turning TypeORM lock errors into 409s in NestJS

A NestJS exception filter catches TypeORM optimistic-lock conflicts and returns a clean HTTP 409 Conflict response.

Explained by highlit
1import {
2 ArgumentsHost,
3 Catch,
4 ConflictException,
5 ExceptionFilter,
6 HttpStatus,
7 Logger,
8} from '@nestjs/common';
9import { HttpAdapterHost } from '@nestjs/core';
10import { OptimisticLockVersionMismatchError } from 'typeorm';
11 
12@Catch(OptimisticLockVersionMismatchError)
13export class OptimisticLockExceptionFilter implements ExceptionFilter {
14 private readonly logger = new Logger(OptimisticLockExceptionFilter.name);
15 
16 constructor(private readonly httpAdapterHost: HttpAdapterHost) {}
17 
18 catch(exception: OptimisticLockVersionMismatchError, host: ArgumentsHost) {
19 const { httpAdapter } = this.httpAdapterHost;
20 const ctx = host.switchToHttp();
21 const request = ctx.getRequest();
22 
23 this.logger.warn(
24 `Optimistic lock conflict on ${request.method} ${request.url}: ${exception.message}`,
25 );
26 
27 const conflict = new ConflictException({
28 statusCode: HttpStatus.CONFLICT,
29 error: 'StaleVersion',
30 message:
31 'The resource was modified by another request. Reload and retry with the latest version.',
32 });
33 
34 httpAdapter.reply(
35 ctx.getResponse(),
36 conflict.getResponse(),
37 HttpStatus.CONFLICT,
38 );
39 }
40}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Exception filters let you translate low-level persistence errors into meaningful HTTP responses in one place.
  2. 2Optimistic locking surfaces concurrent writes as errors you should map to 409 Conflict, not 500.
  3. 3Using the HttpAdapter keeps response writing platform-agnostic across Express and Fastify.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Turning TypeORM lock errors into 409s in NestJS — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code