noctcore-prisma/prisma-tx-uses-tx-not-client
Inside an interactive
$transactioncallback, write through the callback’stx, 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.
What it flags
Section titled “What it flags”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.
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 transactionawait tx.$transaction(async (inner) => { await tx.invoice.create({ data });});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.
What it does not flag
Section titled “What it does not flag”- 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’sthis.client.messages.create(...)whileclientis not inclientProperties).
Options
Section titled “Options”| 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'] }]When not to use it
Section titled “When not to use it”If you never use interactive transactions, this rule has nothing to check.