Skip to content

noctcore-prisma/prisma-tx-uses-tx-not-client

Inside an interactive $transaction callback, write through the callback’s tx, not the outer client.

Recommended preset: error · Autofix: no · Suggestions: no · Type information: not needed

prisma.$transaction(async (tx) => { ... }) only makes the writes that go through tx atomic. A write through the outer client inside the callback runs on a different connection: it commits even when the transaction rolls back. The code reads as transactional and is not.

Inside an interactive $transaction callback whose first parameter is a plain identifier, any Prisma write whose receiver chain is not rooted at that parameter, when the receiver looks like a Prisma client (see receiverPattern, clientProperties, txRootNames) or is rooted at an OUTER transaction’s parameter. Nested transactions each police their own parameter.

Incorrect · 2 reports
await this.prisma.$transaction(async (tx) => {
await tx.invoice.update({ where, data });
await this.prisma.ledgerEntry.create({ data: entry }); // escapes the rollback
});
// nested: the outer tx escapes the inner transaction
await tx.$transaction(async (inner) => {
await tx.invoice.create({ data });
});
Correct
await this.prisma.$transaction(async (tx) => {
await tx.invoice.update({ where, data });
await tx.ledgerEntry.create({ data: entry });
});

Report only: rewriting the receiver is not a trivially safe autofix.

  • Reads through the outer client inside the callback (findMany, count).
  • The array form $transaction([...]), which has no callback.
  • Writes outside any transaction, including a repository’s this.client.account.create(...).
  • A write-named method on something that is not a Prisma client (createHash(...).update(x), this.cache.delete(k), an SDK’s this.client.messages.create(...) while client is not in clientProperties).
Option Type Default Meaning
receiverPattern string (regex source) 'prisma' A name in the receiver chain matching this (case-insensitive) makes it a Prisma client.
clientProperties string[] [] Extra property names that expose a Prisma client, e.g. ['client'] for this.client.invoice.create(...).
txRootNames string[] ['tx'] Root identifiers that are a transaction client even when they are not the active callback’s parameter, e.g. a tx a helper received.
'noctcore-prisma/prisma-tx-uses-tx-not-client': ['error', { clientProperties: ['client'] }]

If you never use interactive transactions, this rule has nothing to check.