diff --git a/packages/client/src/runtime/RequestHandler.ts b/packages/client/src/runtime/RequestHandler.ts index fc9966422a34..f1eaa5778aa0 100644 --- a/packages/client/src/runtime/RequestHandler.ts +++ b/packages/client/src/runtime/RequestHandler.ts @@ -1,6 +1,6 @@ import { Context } from '@opentelemetry/api' import Debug from '@prisma/debug' -import { getTraceParent, TracingConfig } from '@prisma/engine-core' +import { getTraceParent, hasBatchIndex, TracingConfig } from '@prisma/engine-core' import stripAnsi from 'strip-ansi' import { @@ -43,6 +43,7 @@ export type HandleErrorParams = { error: any clientMethod: string callsite?: CallSite + transaction?: PrismaPromiseTransaction } export type Request = { @@ -182,15 +183,22 @@ export class RequestHandler { } return unpackResult } catch (error) { - this.handleRequestError({ error, clientMethod, callsite }) + this.handleRequestError({ error, clientMethod, callsite, transaction }) } } - handleRequestError({ error, clientMethod, callsite }: HandleErrorParams): never { + handleRequestError({ error, clientMethod, callsite, transaction }: HandleErrorParams): never { debug(error) - // TODO: This is a workaround to keep backwards compatibility with clients - // consuming NotFoundError + + if (isMismatchingBatchIndex(error, transaction)) { + // if this is batch error and current request was not it's cause, we don't add + // context information to the error: this wasn't a request that caused batch to fail + throw error + } + if (error instanceof NotFoundError) { + // TODO: This is a workaround to keep backwards compatibility with clients + // consuming NotFoundError throw error } @@ -208,11 +216,19 @@ export class RequestHandler { message = this.sanitizeMessage(message) // TODO: Do request with callsite instead, so we don't need to rethrow if (error.code) { - throw new PrismaClientKnownRequestError(message, error.code, this.client._clientVersion, error.meta) + throw new PrismaClientKnownRequestError(message, { + code: error.code, + clientVersion: this.client._clientVersion, + meta: error.meta, + batchRequestIdx: error.batchRequestIdx, + }) } else if (error.isPanic) { throw new PrismaClientRustPanicError(message, this.client._clientVersion) } else if (error instanceof PrismaClientUnknownRequestError) { - throw new PrismaClientUnknownRequestError(message, this.client._clientVersion) + throw new PrismaClientUnknownRequestError(message, { + clientVersion: this.client._clientVersion, + batchRequestIdx: error.batchRequestIdx, + }) } else if (error instanceof PrismaClientInitializationError) { throw new PrismaClientInitializationError(message, this.client._clientVersion) } else if (error instanceof PrismaClientRustPanicError) { @@ -252,6 +268,10 @@ export class RequestHandler { } } +function isMismatchingBatchIndex(error: any, transaction: PrismaPromiseTransaction | undefined) { + return hasBatchIndex(error) && transaction?.kind === 'batch' && error.batchRequestIdx !== transaction.index +} + /** * Determines which `findUnique` queries can be batched together so that the * query engine can collapse/optimize the queries into a single one. This is diff --git a/packages/client/src/runtime/core/request/PrismaPromise.ts b/packages/client/src/runtime/core/request/PrismaPromise.ts index f63cbcf52637..5e478fbe23bf 100644 --- a/packages/client/src/runtime/core/request/PrismaPromise.ts +++ b/packages/client/src/runtime/core/request/PrismaPromise.ts @@ -4,6 +4,7 @@ export type PrismaPromiseBatchTransaction = { kind: 'batch' id: number isolationLevel?: IsolationLevel + index: number } export type PrismaPromiseInteractiveTransaction = { diff --git a/packages/client/src/runtime/getPrismaClient.ts b/packages/client/src/runtime/getPrismaClient.ts index 3fc7f67fa5a5..2404381f9d97 100644 --- a/packages/client/src/runtime/getPrismaClient.ts +++ b/packages/client/src/runtime/getPrismaClient.ts @@ -56,6 +56,7 @@ import type { InstanceRejectOnNotFound, RejectOnNotFound } from './utils/rejectO import { getRejectOnNotFound } from './utils/rejectOnNotFound' import { serializeRawParameters } from './utils/serializeRawParameters' import { validatePrismaClientOptions } from './utils/validatePrismaClientOptions' +import { waitForBatch } from './utils/waitForBatch' const debug = Debug('prisma:client') const ALTER_RE = /^(\s*alter\s)/i @@ -947,17 +948,17 @@ new PrismaClient({ const txId = this._transactionId++ const lock = getLockCountPromise(promises.length) - const requests = promises.map((request) => { + const requests = promises.map((request, index) => { if (request?.[Symbol.toStringTag] !== 'PrismaPromise') { throw new Error( `All elements of the array need to be Prisma Client promises. Hint: Please make sure you are not awaiting the Prisma client calls you intended to pass in the $transaction function.`, ) } - return request.requestTransaction?.({ id: txId, isolationLevel: options?.isolationLevel }, lock) + return request.requestTransaction?.({ id: txId, index, isolationLevel: options?.isolationLevel }, lock) }) - return Promise.all(requests) + return waitForBatch(requests) } /** diff --git a/packages/client/src/runtime/utils/rejectOnNotFound.ts b/packages/client/src/runtime/utils/rejectOnNotFound.ts index e75384aa7dcd..5fd3f7274f5f 100644 --- a/packages/client/src/runtime/utils/rejectOnNotFound.ts +++ b/packages/client/src/runtime/utils/rejectOnNotFound.ts @@ -17,7 +17,7 @@ export type InstanceRejectOnNotFound = */ export class NotFoundError extends PrismaClientKnownRequestError { constructor(message: string) { - super(message, 'P2025', clientVersion) + super(message, { code: 'P2025', clientVersion }) this.name = 'NotFoundError' } } diff --git a/packages/client/src/runtime/utils/waitForBatch.ts b/packages/client/src/runtime/utils/waitForBatch.ts new file mode 100644 index 000000000000..3eceefef1820 --- /dev/null +++ b/packages/client/src/runtime/utils/waitForBatch.ts @@ -0,0 +1,36 @@ +import { hasBatchIndex } from '@prisma/engine-core' + +/** + * Waits for result of batch $transaction and picks the best possible error to report if any + * of the request fails. Best error is determined as follows: + * + * - if engine have reported and index of failed request in the batch, the best error is the one + * who's index matches that + * - otherwise, first error is used (like Promise.all) + * + * @param promises + * @returns + */ +export async function waitForBatch(promises: T): Promise<{ [K in keyof T]: Awaited }> { + const results = await Promise.allSettled(promises) + + let bestError: unknown = null + const successfulResults = [] as { [K in keyof T]: Awaited } + for (const [i, result] of results.entries()) { + if (result.status === 'rejected') { + const reason = result.reason + if (hasBatchIndex(reason) && reason.batchRequestIdx === i) { + bestError = reason + } else if (!bestError) { + bestError = reason + } + } else { + successfulResults.push(result.value) + } + } + + if (bestError) { + throw bestError + } + return successfulResults +} diff --git a/packages/client/tests/functional/interactive-transactions/__snapshots__/tests.ts.snap b/packages/client/tests/functional/interactive-transactions/__snapshots__/tests.ts.snap index 14991637807a..59dfa5534aea 100644 --- a/packages/client/tests/functional/interactive-transactions/__snapshots__/tests.ts.snap +++ b/packages/client/tests/functional/interactive-transactions/__snapshots__/tests.ts.snap @@ -13,10 +13,10 @@ exports[`interactive-transactions (provider=cockroachdb) batching rollback 1`] = Invalid \`prisma.user.create()\` invocation in /client/tests/functional/interactive-transactions/tests.ts:0:0 - XX 'batching rollback', - XX async () => { - XX const result = prisma.$transaction([ -→ XX prisma.user.create( + XX email: 'user_1@website.com', + XX }, + XX }), +→ XX prisma.user.create( Unique constraint failed on the fields: (\`email\`) `; @@ -37,10 +37,10 @@ exports[`interactive-transactions (provider=mongodb) batching rollback 1`] = ` Invalid \`prisma.user.create()\` invocation in /client/tests/functional/interactive-transactions/tests.ts:0:0 - XX 'batching rollback', - XX async () => { - XX const result = prisma.$transaction([ -→ XX prisma.user.create( + XX email: 'user_1@website.com', + XX }, + XX }), +→ XX prisma.user.create( Unique constraint failed on the constraint: \`User_email_key\` `; @@ -69,10 +69,10 @@ exports[`interactive-transactions (provider=mysql) batching rollback 1`] = ` Invalid \`prisma.user.create()\` invocation in /client/tests/functional/interactive-transactions/tests.ts:0:0 - XX 'batching rollback', - XX async () => { - XX const result = prisma.$transaction([ -→ XX prisma.user.create( + XX email: 'user_1@website.com', + XX }, + XX }), +→ XX prisma.user.create( Unique constraint failed on the constraint: \`User_email_key\` `; @@ -101,10 +101,10 @@ exports[`interactive-transactions (provider=postgresql) batching rollback 1`] = Invalid \`prisma.user.create()\` invocation in /client/tests/functional/interactive-transactions/tests.ts:0:0 - XX 'batching rollback', - XX async () => { - XX const result = prisma.$transaction([ -→ XX prisma.user.create( + XX email: 'user_1@website.com', + XX }, + XX }), +→ XX prisma.user.create( Unique constraint failed on the fields: (\`email\`) `; @@ -133,10 +133,10 @@ exports[`interactive-transactions (provider=sqlite) batching rollback 1`] = ` Invalid \`prisma.user.create()\` invocation in /client/tests/functional/interactive-transactions/tests.ts:0:0 - XX 'batching rollback', - XX async () => { - XX const result = prisma.$transaction([ -→ XX prisma.user.create( + XX email: 'user_1@website.com', + XX }, + XX }), +→ XX prisma.user.create( Unique constraint failed on the fields: (\`email\`) `; @@ -165,10 +165,10 @@ exports[`interactive-transactions (provider=sqlserver) batching rollback 1`] = ` Invalid \`prisma.user.create()\` invocation in /client/tests/functional/interactive-transactions/tests.ts:0:0 - XX 'batching rollback', - XX async () => { - XX const result = prisma.$transaction([ -→ XX prisma.user.create( + XX email: 'user_1@website.com', + XX }, + XX }), +→ XX prisma.user.create( Unique constraint failed on the constraint: \`dbo.User\` `; diff --git a/packages/client/tests/functional/issues/14373-batch-tx-error/_matrix.ts b/packages/client/tests/functional/issues/14373-batch-tx-error/_matrix.ts new file mode 100644 index 000000000000..7a6b8ff0075c --- /dev/null +++ b/packages/client/tests/functional/issues/14373-batch-tx-error/_matrix.ts @@ -0,0 +1,24 @@ +import { defineMatrix } from '../../_utils/defineMatrix' + +export default defineMatrix(() => [ + [ + { + provider: 'sqlite', + }, + { + provider: 'postgresql', + }, + { + provider: 'mysql', + }, + { + provider: 'mongodb', + }, + { + provider: 'cockroachdb', + }, + { + provider: 'sqlserver', + }, + ], +]) diff --git a/packages/client/tests/functional/issues/14373-batch-tx-error/prisma/_schema.ts b/packages/client/tests/functional/issues/14373-batch-tx-error/prisma/_schema.ts new file mode 100644 index 000000000000..a75c03293f54 --- /dev/null +++ b/packages/client/tests/functional/issues/14373-batch-tx-error/prisma/_schema.ts @@ -0,0 +1,22 @@ +import { idForProvider } from '../../../_utils/idForProvider' +import testMatrix from '../_matrix' + +export default testMatrix.setupSchema(({ provider }) => { + return /* Prisma */ ` + generator client { + provider = "prisma-client-js" + } + + datasource db { + provider = "${provider}" + url = env("DATABASE_URI_${provider}") + } + + model User { + id ${idForProvider(provider)} + email String @unique + memo String? + createdAt DateTime @default(now()) + } + ` +}) diff --git a/packages/client/tests/functional/issues/14373-batch-tx-error/tests.ts b/packages/client/tests/functional/issues/14373-batch-tx-error/tests.ts new file mode 100644 index 000000000000..e42a3329420e --- /dev/null +++ b/packages/client/tests/functional/issues/14373-batch-tx-error/tests.ts @@ -0,0 +1,24 @@ +// @ts-ignore +import type { PrismaClient } from '@prisma/client' + +import testMatrix from './_matrix' + +declare let prisma: PrismaClient + +testMatrix.setupTestSuite(() => { + test('correctly reports location of a batch error', async () => { + const result = prisma.$transaction([ + prisma.user.findMany({}), + prisma.user.update({ + where: { + email: 'notthere@example.com', + }, + data: { + memo: 'id is 1', + }, + }), + ]) + + await expect(result).rejects.toThrowError('Invalid `prisma.user.update()` invocation') + }) +}) diff --git a/packages/engine-core/src/binary/BinaryEngine.ts b/packages/engine-core/src/binary/BinaryEngine.ts index d81b94c34be0..6b3c16d4644d 100644 --- a/packages/engine-core/src/binary/BinaryEngine.ts +++ b/packages/engine-core/src/binary/BinaryEngine.ts @@ -493,10 +493,9 @@ ${chalk.dim("In case we're mistaken, please report this to us 🙏.")}`) await this.startPromise if (!this.child && !this.engineEndpoint) { - throw new PrismaClientUnknownRequestError( - `Can't perform request, as the Engine has already been stopped`, - this.clientVersion!, - ) + throw new PrismaClientUnknownRequestError(`Can't perform request, as the Engine has already been stopped`, { + clientVersion: this.clientVersion!, + }) } } @@ -951,7 +950,7 @@ You very likely have the wrong "binaryTarget" defined in the schema.prisma file. throw prismaGraphQLToJSError(data.errors[0], this.clientVersion!) } // this case should not happen, as the query engine only returns one error - throw new PrismaClientUnknownRequestError(JSON.stringify(data.errors), this.clientVersion!) + throw new PrismaClientUnknownRequestError(JSON.stringify(data.errors), { clientVersion: this.clientVersion! }) } // Rust engine returns time in microseconds and we want it in milliseconds @@ -1095,10 +1094,9 @@ You very likely have the wrong "binaryTarget" defined in the schema.prisma file. } if (this.lastErrorLog && isRustErrorLog(this.lastErrorLog)) { - const err = new PrismaClientUnknownRequestError( - this.getErrorMessageWithLink(getMessage(this.lastErrorLog)), - this.clientVersion!, - ) + const err = new PrismaClientUnknownRequestError(this.getErrorMessageWithLink(getMessage(this.lastErrorLog)), { + clientVersion: this.clientVersion!, + }) if (this.lastErrorLog?.fields?.message === 'PANIC') { this.lastPanic = err @@ -1157,7 +1155,7 @@ and your request can't be processed. You probably have some open handle that prevents your process from exiting. It could be an open http server or stream that didn't close yet. We recommend using the \`wtfnode\` package to debug open handles.`, - this.clientVersion!, + { clientVersion: this.clientVersion! }, ) } @@ -1203,12 +1201,11 @@ Please look into the logs or turn on the env var DEBUG=* to debug the constantly */ transactionHttpErrorHandler(result: Result): never { const response = result.data as { [K: string]: unknown } - throw new PrismaClientKnownRequestError( - response.message as string, - response.error_code as string, - this.clientVersion as string, - response.meta, - ) + throw new PrismaClientKnownRequestError(response.message as string, { + code: response.error_code as string, + clientVersion: this.clientVersion as string, + meta: response.meta as Record, + }) } } diff --git a/packages/engine-core/src/common/errors/ErrorWithBatchIndex.ts b/packages/engine-core/src/common/errors/ErrorWithBatchIndex.ts new file mode 100644 index 000000000000..f81da08e288b --- /dev/null +++ b/packages/engine-core/src/common/errors/ErrorWithBatchIndex.ts @@ -0,0 +1,7 @@ +export interface ErrorWithBatchIndex { + batchRequestIdx?: number +} + +export function hasBatchIndex(value: object): value is Required { + return typeof value['batchRequestIdx'] === 'number' +} diff --git a/packages/engine-core/src/common/errors/PrismaClientKnownRequestError.ts b/packages/engine-core/src/common/errors/PrismaClientKnownRequestError.ts index acffc650d832..af86d13c60bb 100644 --- a/packages/engine-core/src/common/errors/PrismaClientKnownRequestError.ts +++ b/packages/engine-core/src/common/errors/PrismaClientKnownRequestError.ts @@ -1,14 +1,25 @@ -export class PrismaClientKnownRequestError extends Error { +import { ErrorWithBatchIndex } from './ErrorWithBatchIndex' + +type KnownErrorParams = { + code: string + clientVersion: string + meta?: Record + batchRequestIdx?: number +} + +export class PrismaClientKnownRequestError extends Error implements ErrorWithBatchIndex { code: string meta?: Record clientVersion: string + batchRequestIdx?: number - constructor(message: string, code: string, clientVersion: string, meta?: any) { + constructor(message: string, { code, clientVersion, meta, batchRequestIdx }: KnownErrorParams) { super(message) this.code = code this.clientVersion = clientVersion this.meta = meta + this.batchRequestIdx = batchRequestIdx } get [Symbol.toStringTag]() { return 'PrismaClientKnownRequestError' diff --git a/packages/engine-core/src/common/errors/PrismaClientUnknownRequestError.ts b/packages/engine-core/src/common/errors/PrismaClientUnknownRequestError.ts index b0fca3a2f92e..92df886bc023 100644 --- a/packages/engine-core/src/common/errors/PrismaClientUnknownRequestError.ts +++ b/packages/engine-core/src/common/errors/PrismaClientUnknownRequestError.ts @@ -1,10 +1,19 @@ -export class PrismaClientUnknownRequestError extends Error { +import { ErrorWithBatchIndex } from './ErrorWithBatchIndex' + +type UnknownErrorParams = { + clientVersion: string + batchRequestIdx?: number +} + +export class PrismaClientUnknownRequestError extends Error implements ErrorWithBatchIndex { clientVersion: string + batchRequestIdx?: number - constructor(message: string, clientVersion: string) { + constructor(message: string, { clientVersion, batchRequestIdx }: UnknownErrorParams) { super(message) this.clientVersion = clientVersion + this.batchRequestIdx = batchRequestIdx } get [Symbol.toStringTag]() { return 'PrismaClientUnknownRequestError' diff --git a/packages/engine-core/src/common/errors/types/RequestError.ts b/packages/engine-core/src/common/errors/types/RequestError.ts index 41f4cecabf93..3e4f687a4439 100644 --- a/packages/engine-core/src/common/errors/types/RequestError.ts +++ b/packages/engine-core/src/common/errors/types/RequestError.ts @@ -3,7 +3,8 @@ export interface RequestError { user_facing_error: { is_panic: boolean message: string - meta?: object + meta?: Record error_code?: string + batch_request_idx?: number } } diff --git a/packages/engine-core/src/common/errors/utils/prismaGraphQLToJSError.ts b/packages/engine-core/src/common/errors/utils/prismaGraphQLToJSError.ts index ffb0e4fc1075..e431b6ee507b 100644 --- a/packages/engine-core/src/common/errors/utils/prismaGraphQLToJSError.ts +++ b/packages/engine-core/src/common/errors/utils/prismaGraphQLToJSError.ts @@ -3,17 +3,20 @@ import { PrismaClientUnknownRequestError } from '../PrismaClientUnknownRequestEr import type { RequestError } from '../types/RequestError' export function prismaGraphQLToJSError( - error: RequestError, + { error, user_facing_error }: RequestError, clientVersion: string, ): PrismaClientKnownRequestError | PrismaClientUnknownRequestError { - if (error.user_facing_error.error_code) { - return new PrismaClientKnownRequestError( - error.user_facing_error.message, - error.user_facing_error.error_code, + if (user_facing_error.error_code) { + return new PrismaClientKnownRequestError(user_facing_error.message, { + code: user_facing_error.error_code, clientVersion, - error.user_facing_error.meta, - ) + meta: user_facing_error.meta, + batchRequestIdx: user_facing_error.batch_request_idx, + }) } - return new PrismaClientUnknownRequestError(error.error, clientVersion) + return new PrismaClientUnknownRequestError(error, { + clientVersion, + batchRequestIdx: user_facing_error.batch_request_idx, + }) } diff --git a/packages/engine-core/src/data-proxy/DataProxyEngine.ts b/packages/engine-core/src/data-proxy/DataProxyEngine.ts index 93f40f2d0ec8..dc65a2592fb9 100644 --- a/packages/engine-core/src/data-proxy/DataProxyEngine.ts +++ b/packages/engine-core/src/data-proxy/DataProxyEngine.ts @@ -208,7 +208,7 @@ export class DataProxyEngine extends Engine { if (data.errors.length === 1) { throw prismaGraphQLToJSError(data.errors[0], this.config.clientVersion!) } else { - throw new PrismaClientUnknownRequestError(data.errors, this.config.clientVersion!) + throw new PrismaClientUnknownRequestError(data.errors, { clientVersion: this.config.clientVersion! }) } } diff --git a/packages/engine-core/src/data-proxy/errors/utils/responseToError.ts b/packages/engine-core/src/data-proxy/errors/utils/responseToError.ts index 7123092a0c9f..ad3910a6f89a 100644 --- a/packages/engine-core/src/data-proxy/errors/utils/responseToError.ts +++ b/packages/engine-core/src/data-proxy/errors/utils/responseToError.ts @@ -95,7 +95,7 @@ export async function responseToError( const error = await getResponseErrorBody(response) if (error.type === 'QueryEngineError') { - throw new PrismaClientKnownRequestError(error.body.message, error.body.error_code, clientVersion) + throw new PrismaClientKnownRequestError(error.body.message, { code: error.body.error_code, clientVersion }) } if (error.type === 'DataProxyError') { diff --git a/packages/engine-core/src/index.ts b/packages/engine-core/src/index.ts index 2159e33929ae..6e24970d4cf9 100644 --- a/packages/engine-core/src/index.ts +++ b/packages/engine-core/src/index.ts @@ -4,6 +4,7 @@ export type { EngineEventType } from './common/Engine' export type { DatasourceOverwrite } from './common/Engine' export type { BatchTransactionOptions } from './common/Engine' export { Engine } from './common/Engine' +export { hasBatchIndex } from './common/errors/ErrorWithBatchIndex' export { PrismaClientInitializationError } from './common/errors/PrismaClientInitializationError' export { PrismaClientKnownRequestError } from './common/errors/PrismaClientKnownRequestError' export { PrismaClientRustPanicError } from './common/errors/PrismaClientRustPanicError' diff --git a/packages/engine-core/src/library/LibraryEngine.ts b/packages/engine-core/src/library/LibraryEngine.ts index 6f1ea2856a5f..2fd701de2b48 100644 --- a/packages/engine-core/src/library/LibraryEngine.ts +++ b/packages/engine-core/src/library/LibraryEngine.ts @@ -146,12 +146,11 @@ export class LibraryEngine extends Engine { const response = this.parseEngineResponse<{ [K: string]: unknown }>(result) if (response.error_code) { - throw new PrismaClientKnownRequestError( - response.message as string, - response.error_code as string, - this.config.clientVersion as string, - response.meta, - ) + throw new PrismaClientKnownRequestError(response.message as string, { + code: response.error_code as string, + clientVersion: this.config.clientVersion as string, + meta: response.meta as Record, + }) } return response as Tx.Info | undefined @@ -188,13 +187,17 @@ You may have to run ${chalk.greenBright('prisma generate')} for your changes to private parseEngineResponse(response?: string): T { if (!response) { - throw new PrismaClientUnknownRequestError(`Response from the Engine was empty`, this.config.clientVersion!) + throw new PrismaClientUnknownRequestError(`Response from the Engine was empty`, { + clientVersion: this.config.clientVersion!, + }) } try { const config = JSON.parse(response) return config as T } catch (err) { - throw new PrismaClientUnknownRequestError(`Unable to JSON.parse response from engine`, this.config.clientVersion!) + throw new PrismaClientUnknownRequestError(`Unable to JSON.parse response from engine`, { + clientVersion: this.config.clientVersion!, + }) } } @@ -460,7 +463,9 @@ You may have to run ${chalk.greenBright('prisma generate')} for your changes to throw this.buildQueryError(data.errors[0]) } // this case should not happen, as the query engine only returns one error - throw new PrismaClientUnknownRequestError(JSON.stringify(data.errors), this.config.clientVersion!) + throw new PrismaClientUnknownRequestError(JSON.stringify(data.errors), { + clientVersion: this.config.clientVersion!, + }) } else if (this.loggerRustPanic) { throw this.loggerRustPanic } @@ -477,7 +482,9 @@ You may have to run ${chalk.greenBright('prisma generate')} for your changes to if (typeof error === 'string') { throw e } else { - throw new PrismaClientUnknownRequestError(`${error.message}\n${error.backtrace}`, this.config.clientVersion!) + throw new PrismaClientUnknownRequestError(`${error.message}\n${error.backtrace}`, { + clientVersion: this.config.clientVersion!, + }) } } } @@ -505,7 +512,9 @@ You may have to run ${chalk.greenBright('prisma generate')} for your changes to throw this.buildQueryError(data.errors[0]) } // this case should not happen, as the query engine only returns one error - throw new PrismaClientUnknownRequestError(JSON.stringify(data.errors), this.config.clientVersion!) + throw new PrismaClientUnknownRequestError(JSON.stringify(data.errors), { + clientVersion: this.config.clientVersion!, + }) } const { batchResult, errors } = data