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 exportsIt 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 |
MappedError → PrismaClientKnownRequestError / 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 executionexecuteRaw/queryRaw— user-supplied raw SQLunique/aggregate/group-by— shaped responsesjoin/attach-children— relation hydrationtransform— projection/typing transformstransaction— wrap a sub-plan in a transactionconcat/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 useROLLBACK TO <name>; SQL Server usesSAVE TRANSACTION <name>andROLLBACK TRANSACTION <name>and has no release statement. - The
Transactioninterface in@prisma/driver-adapter-utilsmodels savepoints as async methods —createSavepoint,rollbackToSavepoint, optionalreleaseSavepoint. This replaces an oldersavepoint(action, name)method that returned SQL strings. TransactionManagerdoes 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
MappedErrorkinds (postgres/mysql/sqlite/mssqlwhose specificoriginalCodethe 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:
- Add the kind to
MappedErrorinpackages/driver-adapter-utils/src/types.ts. - Map the database error code in each affected adapter's
errors.ts. - Add the Prisma code mapping in
getErrorCode()and the message inrenderErrorMessage()inuser-facing-error.ts. - 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/clientthroughLocalExecutor(which callsQueryInterpreter) - Consumed by
@prisma/query-plan-executorfor Accelerate's server-side execution - Imports
@prisma/driver-adapter-utilsforSqlQueryable,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.tsfor the type,interpreter/query-interpreter.tsfor the runtime - Add a new transaction isolation level:
transaction-manager/ - Add a new
MappedErrorkind → Prisma code mapping:user-facing-error.ts - Tweak SQL Commenter behavior:
sql-commenter.ts
See also
- Driver adapters — the adapter contract and per-database errors mapping
@prisma/client— howLocalExecutorinvokes this package@prisma/query-plan-executor— how Accelerate consumes it- Transactions feature — the cross-package narrative
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.