Open-Source Wikis

/

Prisma

/

Packages

/

Client engine runtime

prisma/prisma

Client engine runtime

Active contributors: jacek-prisma, Oleksii Orlenko

Purpose

packages/client-engine-runtime is the core of the Wasm-based client. It exports the QueryInterpreter that walks query plans, the TransactionManager that owns interactive transactions and savepoints, the user-facing error mapper that turns MappedError into Prisma P2xxx codes, and the JSON wire-format types that Prisma Client and Prisma Accelerate share.

The package was extracted from @prisma/client during the Prisma 7 rearchitecture so that Prisma Accelerate's query-plan-executor service could share the exact same execution code as the in-process client. Both consume QueryInterpreter.

Directory layout

packages/client-engine-runtime/src/
├── batch.ts                      # Batch execution helpers
├── crypto.ts                     # Hashing utilities (e.g., for query plan caches)
├── events.ts                     # Trivial event helpers
├── interpreter/
│   └── query-interpreter.ts      # The QueryInterpreter class
├── json-protocol.ts              # JSON wire format types
├── parameterization/             # SQL parameterization helpers
├── query-plan.ts                 # QueryPlan AST type
├── raw-json-protocol.ts          # Raw query JSON wire format
├── schema.ts                     # Schema-related types
├── sql-commenter.ts              # SqlCommenter plugin runtime
├── tracing.ts                    # Tracing utilities
├── transaction-manager/          # TransactionManager
├── user-facing-error.ts          # MappedError → Prisma P2xxx mapping
├── utils.ts                      # Misc
├── web-platform.ts               # Edge runtime detection
└── index.ts                      # Public exports

It also publishes a bench/ directory with interpreter.bench.ts for CodSpeed.

Key abstractions

Symbol File What it does
QueryInterpreter packages/client-engine-runtime/src/interpreter/query-interpreter.ts Walks a QueryPlan and issues calls against a SqlQueryable driver adapter
TransactionManager packages/client-engine-runtime/src/transaction-manager/transaction-manager.ts Owns transaction IDs, isolation levels, and nested transactions via savepoints
QueryPlan type packages/client-engine-runtime/src/query-plan.ts Discriminated union of plan node kinds (queries, transforms, joins, etc.)
MappedError packages/driver-adapter-utils/src/types.ts The normalized adapter error shape this package translates
rethrowAsUserFacing packages/client-engine-runtime/src/user-facing-error.ts MappedErrorPrismaClientKnownRequestError / Prisma error codes
rethrowAsUserFacingRawError packages/client-engine-runtime/src/user-facing-error.ts Raw-query path: always returns P2010
SqlCommenter runtime packages/client-engine-runtime/src/sql-commenter.ts Applies registered SQL Commenter plugins to outgoing SQL

QueryInterpreter

The interpreter receives a QueryPlan (compiled by @prisma/query-compiler-wasm) and a SqlQueryable. It walks plan nodes, issuing queryRaw and executeRaw calls against the queryable. It resolves placeholders, joins relation results, applies filters/orders, and returns shaped JSON.

Plan nodes include things like:

  • query — a literal SQL execution
  • executeRaw / queryRaw — user-supplied raw SQL
  • unique / aggregate / group-by — shaped responses
  • join / attach-children — relation hydration
  • transform — projection/typing transforms
  • transaction — wrap a sub-plan in a transaction
  • concat / union — combine results

(See query-plan.ts for the full union.)

TransactionManager

TransactionManager owns the lifecycle of every interactive transaction and is the single source of truth for transaction IDs.

Important Prisma 7 invariants from AGENTS.md:

  • Savepoint behavior is provider-specific. PostgreSQL uses ROLLBACK TO SAVEPOINT <name>; MySQL/SQLite use ROLLBACK TO <name>; SQL Server uses SAVE TRANSACTION <name> and ROLLBACK TRANSACTION <name> and has no release statement.
  • The Transaction interface in @prisma/driver-adapter-utils models savepoints as async methodscreateSavepoint, rollbackToSavepoint, optional releaseSavepoint. This replaces an older savepoint(action, name) method that returned SQL strings.
  • TransactionManager does not synthesize provider-specific fallback SQL. It calls the adapter's methods, and if the adapter doesn't implement them, the transaction fails. This is intentional — every adapter must own its own savepoint dialect.

Nested transactions are implemented as savepoints. The outer transaction creates a savepoint when a nested call happens; the nested call rolls back to or releases the savepoint when it commits or aborts.

User-facing error mapping

packages/client-engine-runtime/src/user-facing-error.ts is the policy layer between the adapter contract and Prisma's public error surface.

graph LR
    AdapterError[Adapter throws raw DB error] --> Convert[adapter's convertDriverError]
    Convert --> Mapped[MappedError]
    Mapped --> Rethrow[rethrowAsUserFacing]
    Rethrow --> KnownErr[PrismaClientKnownRequestError P2xxx]
    Rethrow -->|unmapped DB code| P2039[P2039 fallback]
    Mapped -->|raw query path| RawRethrow[rethrowAsUserFacingRawError]
    RawRethrow --> P2010[P2010]

Two important error code conventions:

  • P2039 — assigned to unmapped database-specific MappedError kinds (postgres / mysql / sqlite / mssql whose specific originalCode the adapter didn't recognize). Format: Database error. Code: <originalCode>. Message: <originalMessage>. Used for non-raw queries so that schema-drift-style failures stay debuggable instead of becoming opaque HTTP 500s.
  • P2010 — kept for raw queries via rethrowAsUserFacingRawError. Format: Raw query failed. Code: <originalCode>. Message: <originalMessage>.

To add a new error mapping:

  1. Add the kind to MappedError in packages/driver-adapter-utils/src/types.ts.
  2. Map the database error code in each affected adapter's errors.ts.
  3. Add the Prisma code mapping in getErrorCode() and the message in renderErrorMessage() in user-facing-error.ts.
  4. Document the new code in AGENTS.md.

Truly unknown kind values fall through to assertNever, which means new driver-adapter variants surface clearly during development.

SQL Commenter integration

sql-commenter.ts runs plugins from @prisma/sqlcommenter* packages against every outgoing SQL statement. Plugins can read query metadata (model, action, traceparent from OTel) and append a comment to the SQL. See SQL Commenter for the plugin contract.

JSON wire format

json-protocol.ts and raw-json-protocol.ts define the request/response types Prisma Client uses to communicate with both the in-process query compiler (LocalExecutor) and Accelerate's query-plan-executor (RemoteExecutor). Keeping these in a shared package is what makes Accelerate use the exact same execution semantics as the local client.

Integration points

  • Consumed by @prisma/client through LocalExecutor (which calls QueryInterpreter)
  • Consumed by @prisma/query-plan-executor for Accelerate's server-side execution
  • Imports @prisma/driver-adapter-utils for SqlQueryable, Transaction, MappedError
  • No direct dependency on @prisma/client — it's a foundation package

Entry points for modification

  • Add a new query plan node kind: query-plan.ts for the type, interpreter/query-interpreter.ts for the runtime
  • Add a new transaction isolation level: transaction-manager/
  • Add a new MappedError kind → Prisma code mapping: user-facing-error.ts
  • Tweak SQL Commenter behavior: sql-commenter.ts

See also

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Client engine runtime – Prisma wiki | Factory