class SerializationConflictError
extends Error
Since 0.5.0

Thrown when the database rejected a write because a concurrent transaction changed the same data (X38-1, M90f). The operation did not happen and may be retried.

The condition reaches the client as 409 Conflict — the canonical retryable-signal status — instead of the masked 500 that told a well-behaved client to give up, silently dropping the write and making optimistic concurrency unusable. The original driver error is preserved as cause, so the operator's diagnostic still reaches the SQLSTATE (M90j keeps that reachable), while the served detail is the fixed sentence here — never the driver message, which on a pg error quotes the failing statement (X12-3 stays closed).

The detail is also the answer to "what would a caller have been relying on before": a masked 500 carrying Internal Server Error and nothing else, which is not a behaviour any caller can depend on.

Examples

Example 1

import { SerializationConflictError } from '@setu-ts/database-plugin';
try {
  await db.transaction(async (uow) => {
    const row = await uow.getRepository('Account').findById(id);
    await uow.getRepository('Account').update(id, { balance: row.balance - 10 });
  });
} catch (err) {
  if (err instanceof SerializationConflictError) {
    // Retry: the transaction rolled back without applying.
  }
}

Constructors

SerializationConflictError(
message: string,
options?: { cause?: unknown; }
)

Creates the error. The message is the full diagnostic — safe to log, never to serve.

Parameters
message: string

The full diagnostic, safe to log

optional
options: { cause?: unknown; }

The original driver error, preserved as cause

Properties

readonly
name: string

Discriminant for consumers that cannot use instanceof across realms.

Usage

import { SerializationConflictError } from "database-plugin/src/index.ts";