Skip to content

fix(client-engine-runtime): surface unmapped driver errors as user-facing P2039 - #29512

Merged
aqrln merged 1 commit into
mainfrom
aqrln-nlupksywpnyp
Apr 27, 2026
Merged

fix(client-engine-runtime): surface unmapped driver errors as user-facing P2039#29512
aqrln merged 1 commit into
mainfrom
aqrln-nlupksywpnyp

Conversation

@aqrln

@aqrln aqrln commented Apr 24, 2026

Copy link
Copy Markdown
Member

Closes https://linear.app/prisma-company/issue/TML-2092/customer-support-issue-qpe-crash-on-prisma-710

When a driver adapter error arrived with kind: 'postgres' (or mysql / sqlite / mssql) and the adapter did not map the underlying database error code to a more specific MappedError kind, rethrowAsUserFacing rethrew the raw DriverAdapterError unchanged.

Locally, that surfaced as PrismaClientUnknownRequestError. Worse, the query plan executor returned HTTP 500 with the real error message in the body, and Accelerate strips 500 response bodies, so end users only saw a generic P6000 with no way to diagnose the underlying problem.

This commonly happens on schema drift — e.g. an upsert() targeting a column whose unique index was dropped in the DB raises Postgres 42P10 ("there is no unique or exclusion constraint matching the ON CONFLICT specification"), which is not individually mapped by the adapter. These errors are not bugs and end users need to see the underlying DB code and message to debug.

Fix

When getErrorCode / renderErrorMessage have no specific mapping for a database-specific kind, fall back to a P2039 UserFacingError with the format Database error. Code: `X`. Message: `Y` carrying the raw originalCode / originalMessage. Consequences:

  1. Locally, the error is a PrismaClientKnownRequestError(P2039, …) with the real DB details.
  2. The query plan executor returns HTTP 400 with the structured error, which Accelerate forwards unchanged.
  3. Truly unknown kinds (e.g. new variants from a driver-adapter ahead of the client) still fall through to assertNever so they remain visible during development.

P2010 "Raw query failed." is kept as-is for $executeRaw / $queryRaw via rethrowAsUserFacingRawError, so non-raw queries no longer claim to be raw in their error message.

P2038 and P2039 are allocated outside the public Error Reference; both are now documented in AGENTS.md and cross-referenced from the code. We need to add them to the public docs.

Tests

  • New unit tests in packages/client-engine-runtime/src/user-facing-error.test.ts covering all four DB kinds, missing originalCode/originalMessage, raw-query parity (P2010 still), and a regression guard that specifically-mapped kinds (e.g. UniqueConstraintViolation → P2002) still win over the fallback.
  • New functional regression test in packages/client/tests/functional/issues/unmapped-driver-error-user-facing/ that reproduces the real 42P10 upsert scenario by dropping the unique index and asserting PrismaClientKnownRequestError(P2039, …) with the raw DB details. Passes locally against js_pg, js_neon, and the QPE (--remote-executor) path.

@coderabbitai

coderabbitai Bot commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Summary by CodeRabbit

  • New Features

    • Unmapped database errors now surface a generic user-facing error (P2039) that includes the original DB error code and message for clearer diagnostics.
  • Bug Fixes

    • Raw and non-raw query errors are distinguished consistently (raw queries retain P2010), preventing misleading messages.
  • Documentation

    • Clarified adapter error-handling behavior and documented fallback error codes (including P2038/P2039).
  • Tests

    • Added regression and functional tests covering unmapped-driver and raw-query error formatting.

Walkthrough

Unmapped driver-adapter errors for postgres/mysql/sqlite/mssql now surface as a P2039 UserFacingError embedding the adapter originalCode/originalMessage; raw queries continue using P2010. Docs, unit tests, and a PostgreSQL functional regression test were added/updated; minor client docs comment added for P2038.

Changes

Cohort / File(s) Summary
Documentation
AGENTS.md, packages/client/src/runtime/core/engines/client/ClientEngine.ts
Documents new P2039 unmapped-driver fallback and records P2038 as the client-engine error code; adds note about raw vs non-raw messaging behavior.
Core error handling
packages/client-engine-runtime/src/user-facing-error.ts
Refactors rethrow logic and helpers: centralizes raw-query error construction, uses pickErrorMessage, and throws P2039 for unmapped postgres/mysql/sqlite/mssql adapter errors while preserving driverAdapterError meta.
Unit tests (error handling)
packages/client-engine-runtime/src/user-facing-error.test.ts
Adds tests for P2039 unmapped-adapter behavior (including N/A fallbacks), verifies raw queries still produce P2010, and ensures existing specific mappings are preserved.
Functional regression (Postgres)
packages/client/tests/functional/issues/unmapped-driver-error-user-facing/_matrix.ts, packages/client/tests/functional/issues/unmapped-driver-error-user-facing/prisma/_schema.ts, packages/client/tests/functional/issues/unmapped-driver-error-user-facing/test.ts
Adds PostgreSQL-only functional test that drops a unique index to trigger a DB error (42P10) and asserts Client surfaces P2039 with original DB code/message.
Test normalization tweak
packages/client/tests/functional/fulltext-search/tests.ts
Adjusts error normalization to extract the DB message from Prisma’s Code: \X`. Message: `Y`` formatted error, falling back when not matched.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: surfacing unmapped driver errors as a user-facing P2039 error code, which is the primary focus of this PR.
Description check ✅ Passed The description is directly related to the changeset, explaining the problem, the fix, and the testing approach for surfacing unmapped driver errors as user-facing P2039.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch aqrln-nlupksywpnyp
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch aqrln-nlupksywpnyp

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

Path Size
packages/client/runtime/index-browser.js 2.29 KB (0%)
packages/client/runtime/index-browser.d.ts 3.37 KB (0%)
packages/cli/build/index.js 2.54 MB (0%)
packages/client/prisma-client-0.0.0.tgz 26.83 MB (+0.02% 🔺)
packages/cli/prisma-0.0.0.tgz 13.53 MB (0%)
packages/bundle-size/da-workers-libsql/output.tgz 1.33 MB (+0.01% 🔺)
packages/bundle-size/da-workers-neon/output.tgz 1.39 MB (+0.01% 🔺)
packages/bundle-size/da-workers-pg/output.tgz 1.39 MB (+0.01% 🔺)
packages/bundle-size/da-workers-planetscale/output.tgz 1.33 MB (+0.01% 🔺)
packages/bundle-size/da-workers-d1/output.tgz 1.31 MB (+0.01% 🔺)

@aqrln
aqrln force-pushed the aqrln-nlupksywpnyp branch from 82608c4 to c823618 Compare April 24, 2026 10:35

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/client-engine-runtime/src/user-facing-error.ts (1)

78-92: ⚠️ Potential issue | 🟠 Major

Fallback message can degrade to ``Message: undefined``` when adapter omits originalMessage`.

At Line 91 (and similarly Line 81), renderErrorMessage(error) is undefined for generic DB kinds, so missing originalMessage leaks an unusable message string.

💡 Suggested fix
 function buildRawQueryUserFacingError(error: DriverAdapterError): UserFacingError {
   return new UserFacingError(
-    `Raw query failed. Code: \`${error.cause.originalCode ?? 'N/A'}\`. Message: \`${
-      error.cause.originalMessage ?? renderErrorMessage(error)
-    }\``,
+    `Raw query failed. Code: \`${getOriginalCode(error)}\`. Message: \`${getOriginalMessage(error)}\``,
     'P2010',
     { driverAdapterError: error },
   )
 }
 
 function buildUnmappedDatabaseUserFacingError(error: DriverAdapterError): UserFacingError {
   return new UserFacingError(
-    `Database error. Code: \`${error.cause.originalCode ?? 'N/A'}\`. Message: \`${
-      error.cause.originalMessage ?? renderErrorMessage(error)
-    }\``,
+    `Database error. Code: \`${getOriginalCode(error)}\`. Message: \`${getOriginalMessage(error)}\``,
     'P2039',
     { driverAdapterError: error },
   )
 }
+
+function getOriginalCode(error: DriverAdapterError): string {
+  return error.cause.originalCode ?? 'N/A'
+}
+
+function getOriginalMessage(error: DriverAdapterError): string {
+  if (typeof error.cause.originalMessage === 'string') return error.cause.originalMessage
+  if ('message' in error.cause && typeof error.cause.message === 'string') return error.cause.message
+  return 'N/A'
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/client-engine-runtime/src/user-facing-error.ts` around lines 78 -
92, The templates in buildRawQueryUserFacingError and
buildUnmappedDatabaseUserFacingError can produce "Message: `undefined`" because
renderErrorMessage(error) may return undefined; update both functions to
coalesce the message fallback to a safe string (e.g., 'N/A' or 'No message
provided') instead of allowing undefined — use the combined fallback
error.cause.originalMessage ?? renderErrorMessage(error) ?? 'N/A' (or similar)
so the constructed UserFacingError message never embeds undefined.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/client-engine-runtime/src/user-facing-error.test.ts`:
- Around line 113-135: The current test "rethrowAsUserFacing falls back to N/A
when originalCode/originalMessage are missing" uses a loose prefix match on
userFacing.message so a literal "undefined" can slip through; tighten the
assertion for rethrowAsUserFacing/UserFacingError by replacing the partial match
on userFacing.message with a stricter regex that anchors the entire message and
disallows the string "undefined" (for example match ^Database error\. Code:
`N\/A`\. Message: `[^`]+`$ or alternatively add
expect(userFacing.message).not.toMatch(/undefined/)); update the assertion that
references userFacing.message in this test to use the stricter check.

---

Outside diff comments:
In `@packages/client-engine-runtime/src/user-facing-error.ts`:
- Around line 78-92: The templates in buildRawQueryUserFacingError and
buildUnmappedDatabaseUserFacingError can produce "Message: `undefined`" because
renderErrorMessage(error) may return undefined; update both functions to
coalesce the message fallback to a safe string (e.g., 'N/A' or 'No message
provided') instead of allowing undefined — use the combined fallback
error.cause.originalMessage ?? renderErrorMessage(error) ?? 'N/A' (or similar)
so the constructed UserFacingError message never embeds undefined.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 45bf4feb-9544-403a-84e5-62671b9f6cf3

📥 Commits

Reviewing files that changed from the base of the PR and between 82608c4 and c823618.

⛔ Files ignored due to path filters (1)
  • packages/client/tests/functional/fulltext-search/__snapshots__/tests.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (8)
  • AGENTS.md
  • packages/client-engine-runtime/src/user-facing-error.test.ts
  • packages/client-engine-runtime/src/user-facing-error.ts
  • packages/client/src/runtime/core/engines/client/ClientEngine.ts
  • packages/client/tests/functional/fulltext-search/tests.ts
  • packages/client/tests/functional/issues/unmapped-driver-error-user-facing/_matrix.ts
  • packages/client/tests/functional/issues/unmapped-driver-error-user-facing/prisma/_schema.ts
  • packages/client/tests/functional/issues/unmapped-driver-error-user-facing/test.ts

Comment thread packages/client-engine-runtime/src/user-facing-error.test.ts
@aqrln
aqrln force-pushed the aqrln-nlupksywpnyp branch 2 times, most recently from 50d7ed7 to 4a0772a Compare April 27, 2026 09:18

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/client-engine-runtime/src/user-facing-error.ts (1)

78-95: ⚠️ Potential issue | 🟠 Major

Fallback message construction can still emit ``Message: `undefined``` for unmapped DB errors.

When originalMessage is missing, renderErrorMessage(error) is also undefined for database-specific kinds (Line 237-241), so both P2039 and P2010 builders can generate unusable output.

Suggested fix
 function buildRawQueryUserFacingError(error: DriverAdapterError): UserFacingError {
   return new UserFacingError(
-    `Raw query failed. Code: \`${error.cause.originalCode ?? 'N/A'}\`. Message: \`${
-      error.cause.originalMessage ?? renderErrorMessage(error)
-    }\``,
+    `Raw query failed. Code: \`${error.cause.originalCode ?? 'N/A'}\`. Message: \`${resolveDatabaseMessage(error)}\``,
     'P2010',
     { driverAdapterError: error },
   )
 }
 
 function buildUnmappedDatabaseUserFacingError(error: DriverAdapterError): UserFacingError {
   return new UserFacingError(
-    `Database error. Code: \`${error.cause.originalCode ?? 'N/A'}\`. Message: \`${
-      error.cause.originalMessage ?? renderErrorMessage(error)
-    }\``,
+    `Database error. Code: \`${error.cause.originalCode ?? 'N/A'}\`. Message: \`${resolveDatabaseMessage(error)}\``,
     'P2039',
     { driverAdapterError: error },
   )
 }
+
+function resolveDatabaseMessage(error: DriverAdapterError): string {
+  if (error.cause.originalMessage) return error.cause.originalMessage
+
+  const mappedMessage = renderErrorMessage(error)
+  if (mappedMessage) return mappedMessage
+
+  const causeMessage = (error.cause as { message?: unknown }).message
+  if (typeof causeMessage === 'string' && causeMessage.length > 0) return causeMessage
+
+  return 'N/A'
+}

Also applies to: 237-241

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/client-engine-runtime/src/user-facing-error.ts` around lines 78 -
95, Both buildRawQueryUserFacingError and buildUnmappedDatabaseUserFacingError
can produce Message: `undefined` when error.cause.originalMessage and
renderErrorMessage(error) are both undefined; update both functions so the
message fallback is a safe string (e.g. use error.cause.originalMessage ??
renderErrorMessage(error) ?? 'N/A' or 'No message provided') when building the
template, ensuring the generated UserFacingError never contains `undefined`.
♻️ Duplicate comments (1)
packages/client-engine-runtime/src/user-facing-error.test.ts (1)

134-134: ⚠️ Potential issue | 🟡 Minor

Strengthen the missing-fields assertion to block ``Message: `undefined``` regressions.

Line 134 only checks a prefix, so malformed fallback output can still pass.

Suggested fix
-    expect(userFacing.message).toMatch(/^Database error\. Code: `N\/A`\. Message: `/)
+    expect(userFacing.message).toMatch(/^Database error\. Code: `N\/A`\. Message: `[^`]+`$/)
+    expect(userFacing.message).not.toContain('`undefined`')
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/client-engine-runtime/src/user-facing-error.test.ts` at line 134,
The current test only checks the prefix of userFacing.message and can miss a
fallback of "Message: `undefined`"; update the assertion in
user-facing-error.test.ts to more strictly validate the message by either
matching the full expected fallback pattern (e.g., ensure it includes a
backticked message placeholder) or add an explicit negative assertion against
/Message: `undefined`/ so the test fails if the fallback becomes the literal
"undefined"; target the existing expect(userFacing.message) assertion and
replace/augment it accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@packages/client/tests/functional/issues/unmapped-driver-error-user-facing/test.ts`:
- Line 44: The DROP INDEX call in the test setup uses await
prisma.$executeRawUnsafe(`DROP INDEX "User_email_key"`) which can fail if the
index is already absent; make the setup idempotent by changing that raw SQL to
use IF EXISTS (i.e., DROP INDEX IF EXISTS ...) so reruns or partial setups don't
cause spurious failures and the regression assertion remains the only failure
point.

---

Outside diff comments:
In `@packages/client-engine-runtime/src/user-facing-error.ts`:
- Around line 78-95: Both buildRawQueryUserFacingError and
buildUnmappedDatabaseUserFacingError can produce Message: `undefined` when
error.cause.originalMessage and renderErrorMessage(error) are both undefined;
update both functions so the message fallback is a safe string (e.g. use
error.cause.originalMessage ?? renderErrorMessage(error) ?? 'N/A' or 'No message
provided') when building the template, ensuring the generated UserFacingError
never contains `undefined`.

---

Duplicate comments:
In `@packages/client-engine-runtime/src/user-facing-error.test.ts`:
- Line 134: The current test only checks the prefix of userFacing.message and
can miss a fallback of "Message: `undefined`"; update the assertion in
user-facing-error.test.ts to more strictly validate the message by either
matching the full expected fallback pattern (e.g., ensure it includes a
backticked message placeholder) or add an explicit negative assertion against
/Message: `undefined`/ so the test fails if the fallback becomes the literal
"undefined"; target the existing expect(userFacing.message) assertion and
replace/augment it accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 7be822cf-1133-425a-ad31-be240715b49d

📥 Commits

Reviewing files that changed from the base of the PR and between c823618 and 50d7ed7.

⛔ Files ignored due to path filters (1)
  • packages/client/tests/functional/fulltext-search/__snapshots__/tests.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (8)
  • AGENTS.md
  • packages/client-engine-runtime/src/user-facing-error.test.ts
  • packages/client-engine-runtime/src/user-facing-error.ts
  • packages/client/src/runtime/core/engines/client/ClientEngine.ts
  • packages/client/tests/functional/fulltext-search/tests.ts
  • packages/client/tests/functional/issues/unmapped-driver-error-user-facing/_matrix.ts
  • packages/client/tests/functional/issues/unmapped-driver-error-user-facing/prisma/_schema.ts
  • packages/client/tests/functional/issues/unmapped-driver-error-user-facing/test.ts

@aqrln aqrln added this to the 7.9.0 milestone Apr 27, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
packages/client/tests/functional/issues/unmapped-driver-error-user-facing/test.ts (1)

44-44: ⚠️ Potential issue | 🟡 Minor

Make setup idempotent when dropping the unique index.

Line 44 can fail if the index is already absent, which makes this regression test flaky for reruns/retries.

Proposed fix
-      await prisma.$executeRawUnsafe(`DROP INDEX "User_email_key"`)
+      await prisma.$executeRawUnsafe(`DROP INDEX IF EXISTS "User_email_key"`)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/client/tests/functional/issues/unmapped-driver-error-user-facing/test.ts`
at line 44, The test setup should tolerate the index already being absent;
update the prisma.$executeRawUnsafe call that drops the unique index (the
statement `DROP INDEX "User_email_key"`) to be idempotent by either using the
DB-safe form `DROP INDEX IF EXISTS "User_email_key"` or by wrapping the
prisma.$executeRawUnsafe call in a try/catch and ignoring the specific “index
does not exist” error; modify the code that calls prisma.$executeRawUnsafe
accordingly so reruns/retries of the test won't fail.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/client-engine-runtime/src/user-facing-error.ts`:
- Around line 36-38: Replace the truthy check "if (code && message)" with
explicit undefined checks so empty strings are treated as valid mapped values;
in the UserFacingError creation path (in user-facing-error.ts) change the
condition to "if (code !== undefined && message !== undefined)" (or equivalent
explicit checks for both variables) so a mapped kind with empty-string message
or code doesn't fall through to rethrowing the raw error, then keep throwing new
UserFacingError(message, code, { driverAdapterError: error }) unchanged.

In `@packages/client/src/runtime/core/engines/client/ClientEngine.ts`:
- Around line 44-48: Remove the redundant JSDoc that describes what the constant
is; delete the comment block immediately above the CLIENT_ENGINE_ERROR constant
and leave the const CLIENT_ENGINE_ERROR = 'P2038' declaration as-is, since its
usage (where CLIENT_ENGINE_ERROR is thrown) documents its purpose and the
constant is not exported; keep no additional comment or replace it only with a
short "internal Prisma error code" inline note if you think brief context is
necessary.

---

Duplicate comments:
In
`@packages/client/tests/functional/issues/unmapped-driver-error-user-facing/test.ts`:
- Line 44: The test setup should tolerate the index already being absent; update
the prisma.$executeRawUnsafe call that drops the unique index (the statement
`DROP INDEX "User_email_key"`) to be idempotent by either using the DB-safe form
`DROP INDEX IF EXISTS "User_email_key"` or by wrapping the
prisma.$executeRawUnsafe call in a try/catch and ignoring the specific “index
does not exist” error; modify the code that calls prisma.$executeRawUnsafe
accordingly so reruns/retries of the test won't fail.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 54752013-1fc8-425b-861e-33a628453643

📥 Commits

Reviewing files that changed from the base of the PR and between 50d7ed7 and 4a0772a.

⛔ Files ignored due to path filters (1)
  • packages/client/tests/functional/fulltext-search/__snapshots__/tests.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (8)
  • AGENTS.md
  • packages/client-engine-runtime/src/user-facing-error.test.ts
  • packages/client-engine-runtime/src/user-facing-error.ts
  • packages/client/src/runtime/core/engines/client/ClientEngine.ts
  • packages/client/tests/functional/fulltext-search/tests.ts
  • packages/client/tests/functional/issues/unmapped-driver-error-user-facing/_matrix.ts
  • packages/client/tests/functional/issues/unmapped-driver-error-user-facing/prisma/_schema.ts
  • packages/client/tests/functional/issues/unmapped-driver-error-user-facing/test.ts

Comment thread packages/client-engine-runtime/src/user-facing-error.ts Outdated
Comment thread packages/client/src/runtime/core/engines/client/ClientEngine.ts
…cing P2039

When a driver adapter error arrived with `kind: 'postgres'` (or `mysql` /
`sqlite` / `mssql`) and the adapter did not map the underlying database
error code to a more specific `MappedError` kind, `rethrowAsUserFacing`
rethrew the raw `DriverAdapterError` unchanged.

Locally, that surfaced as `PrismaClientUnknownRequestError`. Worse, the
query plan executor returned HTTP 500 with the real error message in the
body, and Accelerate strips 500 response bodies, so end users only saw a
generic P6000 with no way to diagnose the underlying problem.

This commonly happens on schema drift — e.g. an `upsert()` targeting a
column whose unique index was dropped in the DB raises Postgres 42P10
("there is no unique or exclusion constraint matching the ON CONFLICT
specification"), which is not individually mapped by the adapter. These
errors are not bugs and end users need to see the underlying DB code and
message to debug.

Fix: when `getErrorCode` / `renderErrorMessage` have no specific mapping
for a database-specific kind, fall back to a P2039 `UserFacingError` with
the format `Database error. Code: \`X\`. Message: \`Y\`` carrying the
raw `originalCode` / `originalMessage`. Consequences:

  1. Locally, the error is a `PrismaClientKnownRequestError(P2039, …)`
     with the real DB details.
  2. The query plan executor returns HTTP 400 with the structured error,
     which Accelerate forwards unchanged.
  3. Truly unknown kinds (e.g. new variants from a driver-adapter ahead
     of the client) still fall through to `assertNever` so they remain
     visible during development.

P2010 "Raw query failed." is kept as-is for `$executeRaw` / `$queryRaw`
via `rethrowAsUserFacingRawError`, so non-raw queries no longer claim to
be raw in their error message.

P2038 and P2039 are allocated outside the public Error Reference; both
are now documented in `AGENTS.md` and cross-referenced from the code.
@aqrln
aqrln force-pushed the aqrln-nlupksywpnyp branch from 4a0772a to 7922c6f Compare April 27, 2026 09:29

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (2)
packages/client/src/runtime/core/engines/client/ClientEngine.ts (1)

44-47: 🧹 Nitpick | 🔵 Trivial

Consider removing the JSDoc comment.

This concern was previously raised: the comment documents what the error code is used for, which is already evident from its usage at lines 129-133. Since CLIENT_ENGINE_ERROR is not exported, it should not have a JSDoc comment per coding guidelines. As per coding guidelines, comments should explain why (context, decisions) rather than what, and documentation comments are for exported items.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/client/src/runtime/core/engines/client/ClientEngine.ts` around lines
44 - 47, Remove the redundant JSDoc that describes the Prisma error code for
CLIENT_ENGINE_ERROR; since CLIENT_ENGINE_ERROR is not exported and the comment
only restates what the constant does, delete the JSDoc block above the
CLIENT_ENGINE_ERROR declaration in ClientEngine.ts and leave a brief inline
comment only if needed for rationale (not what) per guidelines.
packages/client/tests/functional/issues/unmapped-driver-error-user-facing/test.ts (1)

44-44: ⚠️ Potential issue | 🟡 Minor

Make the index drop idempotent in test setup.

Line 44 can fail on reruns if the index is already absent, which makes the setup flaky and can hide the actual regression signal.

Proposed fix
-      await prisma.$executeRawUnsafe(`DROP INDEX "User_email_key"`)
+      await prisma.$executeRawUnsafe(`DROP INDEX IF EXISTS "User_email_key"`)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/client/tests/functional/issues/unmapped-driver-error-user-facing/test.ts`
at line 44, The test setup currently calls prisma.$executeRawUnsafe(`DROP INDEX
"User_email_key"`) which fails if the index is already absent; make this
idempotent by either using a conditional drop (e.g. `DROP INDEX IF EXISTS
"User_email_key"`) in the prisma.$executeRawUnsafe call or wrapping the existing
prisma.$executeRawUnsafe(...) in a try/catch that ignores the specific “index
does not exist” error; update the call site (the prisma.$executeRawUnsafe
invocation) accordingly so rerunning the test won’t error.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@packages/client/src/runtime/core/engines/client/ClientEngine.ts`:
- Around line 44-47: Remove the redundant JSDoc that describes the Prisma error
code for CLIENT_ENGINE_ERROR; since CLIENT_ENGINE_ERROR is not exported and the
comment only restates what the constant does, delete the JSDoc block above the
CLIENT_ENGINE_ERROR declaration in ClientEngine.ts and leave a brief inline
comment only if needed for rationale (not what) per guidelines.

In
`@packages/client/tests/functional/issues/unmapped-driver-error-user-facing/test.ts`:
- Line 44: The test setup currently calls prisma.$executeRawUnsafe(`DROP INDEX
"User_email_key"`) which fails if the index is already absent; make this
idempotent by either using a conditional drop (e.g. `DROP INDEX IF EXISTS
"User_email_key"`) in the prisma.$executeRawUnsafe call or wrapping the existing
prisma.$executeRawUnsafe(...) in a try/catch that ignores the specific “index
does not exist” error; update the call site (the prisma.$executeRawUnsafe
invocation) accordingly so rerunning the test won’t error.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 541a4116-1613-4eb2-ab86-bab59638f461

📥 Commits

Reviewing files that changed from the base of the PR and between 4a0772a and 7922c6f.

⛔ Files ignored due to path filters (1)
  • packages/client/tests/functional/fulltext-search/__snapshots__/tests.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (8)
  • AGENTS.md
  • packages/client-engine-runtime/src/user-facing-error.test.ts
  • packages/client-engine-runtime/src/user-facing-error.ts
  • packages/client/src/runtime/core/engines/client/ClientEngine.ts
  • packages/client/tests/functional/fulltext-search/tests.ts
  • packages/client/tests/functional/issues/unmapped-driver-error-user-facing/_matrix.ts
  • packages/client/tests/functional/issues/unmapped-driver-error-user-facing/prisma/_schema.ts
  • packages/client/tests/functional/issues/unmapped-driver-error-user-facing/test.ts

@aqrln
aqrln merged commit 0036baf into main Apr 27, 2026
496 of 500 checks passed
@aqrln
aqrln deleted the aqrln-nlupksywpnyp branch April 27, 2026 16:59
owine added a commit to owine/house-manager that referenced this pull request Jul 27, 2026
Unblocks #302 (Prisma 7.9.0), where
`tests/integration/vendor-delete-flow.test.ts` fails two cases.

## What broke

`@prisma/adapter-pg` has never mapped pg18's SQLSTATE `23001`
(`restrict_violation`) to Prisma's `P2003`, so `tryDeleteVendor` has
always had to sniff the raw error. **7.9.0 changed the shape of that raw
error**, per its own release notes:

> Unmapped database errors from driver adapters now surface as a
user-facing `P2039` (`PrismaClientKnownRequestError`) carrying the
original code and message, instead of an opaque failure
([prisma#29512](prisma/orm#29512)).

Captured against pg18 by deleting a vendor that still has an
`ItemVendor` link:

| | 7.8.0 | 7.9.0 |
|---|---|---|
| Error class | raw `DriverAdapterError` |
`PrismaClientKnownRequestError` |
| `err.code` | — | `"P2039"` (not `P2003`) |
| `err.cause` | `{ code: '23001' }` | **undefined** |
| SQLSTATE at | `err.cause.code` |
`err.meta.driverAdapterError.cause.code` |

The existing guard checked `err.code === 'P2003'` (false — it's `P2039`)
and `err.cause?.code` (undefined — there is no `cause` any more). Both
fail, so a RESTRICT violation escapes `tryDeleteVendor` as a raw throw
instead of becoming the structured link-count result the UI needs — and
a server action must never throw.

## The fix

The SQLSTATE is **stable at `23001` across both versions**; only the
envelope moved. So `lib/db-errors.ts` reads every known location rather
than pattern-matching one adapter version. This has now broken twice on
a minor bump; the next envelope change should not break it a third time.

The second commit removes the module's `@prisma/client` import:

- It only reads the *shape* of an error, so depending on the generated
client made its unit test require `prisma generate` to have run first —
which is how it surfaced (the file collected 0 tests).
- It also drops `instanceof PrismaClientKnownRequestError`. Under pnpm
two copies of `@prisma/client` can be loaded, and an error built by one
would not match the class from the other — the check would silently
return `false`, which is precisely the failure mode this module exists
to prevent.

## Why a separate PR

The fix is independent of the bump — it makes detection robust on 7.8.0
too. Landing it here means #302 only needs a rebase, and Renovate
force-pushes its own branch.

## Testing

The unit tests carry the **real captured error shapes from both 7.8.0
and 7.9.0**, and need no database. This regression was previously only
reachable through an integration test against a live pg18, which is why
a minor bump could break it silently — now a shape change fails a unit
test.

Verified `tests/integration/vendor-delete-flow.test.ts` **9/9 on both
versions** (7.9.0 checked in a worktree with the bumped deps installed;
those two cases fail there without this change).

## Other 7.9.0 upgrade notes reviewed

- **`$queryRaw` now rejects invalid `Date`s** instead of silently
serializing `null` — checked every raw query in `lib/`, `worker/`, none
bind a `Date`. No action.
- **Interactive-transaction connection-leak fix** — we have 10
`$transaction` call sites on `adapter-pg`; this is a fix we benefit
from.
- **TypeScript perf regression fixed** (`OmitOpts` generic default
restored) — relevant given this repo's schema size.
- **AI-agent safety checkpoint broadened** (detects `CLAUDECODE`, gated
by `PRISMA_USER_CONSENT_FOR_DANGEROUS_AI_ACTION`). Verified it does
**not** fire for `migrate dev` or `migrate reset` in this setup.

https://claude.ai/code/session_01Wht5WVMSC1Z3qhm3GCrJeC

## Summary by Sourcery

Improve detection of foreign-key constraint violations in vendor
deletion to be robust across Prisma adapter versions and error shapes.

Bug Fixes:
- Prevent vendor deletion from throwing unhandled errors when PostgreSQL
emits RESTRICT-mode foreign-key violations with adapter-specific error
envelopes.
- Ensure foreign-key violations are consistently converted into
structured results for the vendor delete flow instead of leaking raw
adapter errors.

Enhancements:
- Centralize Prisma/Postgres error shape handling in a new db-errors
helper that structurally inspects error objects without depending on
@prisma/client.

Tests:
- Add unit tests covering SQLSTATE extraction and foreign-key violation
detection for multiple Prisma adapter versions and error shapes,
replacing reliance on integration-only coverage.
OIRNOIR pushed a commit to OIRNOIR/YouTube-Helper-Server that referenced this pull request Jul 28, 2026
This PR contains the following updates:

| Package | Type | Update | Change | Pending |
|---|---|---|---|---|
| [@prisma/adapter-pg](https://github.com/prisma/prisma) ([source](https://github.com/prisma/prisma/tree/HEAD/packages/adapter-pg)) | imports | minor | [`7.8.0` -> `7.9.0`](https://renovatebot.com/diffs/npm/@prisma%2fadapter-pg/7.8.0/7.9.0) | `7.9.1` |
| [@prisma/client](https://www.prisma.io) ([source](https://github.com/prisma/prisma/tree/HEAD/packages/client)) | imports | minor | [`7.8.0` -> `7.9.0`](https://renovatebot.com/diffs/npm/@prisma%2fclient/7.8.0/7.9.0) | `7.9.1` |
| [prisma](https://www.prisma.io) ([source](https://github.com/prisma/prisma/tree/HEAD/packages/cli)) | imports | minor | [`7.8.0` -> `7.9.0`](https://renovatebot.com/diffs/npm/prisma/7.8.0/7.9.0) | `7.9.1` |

---

### Release Notes

<details>
<summary>prisma/prisma (@&#8203;prisma/adapter-pg)</summary>

### [`v7.9.0`](https://github.com/prisma/prisma/releases/tag/7.9.0)

[Compare Source](prisma/orm@7.8.0...7.9.0)

Today, we are excited to share the `7.9.0` stable release 🎉

**🌟 Star this repo for notifications about new releases, bug fixes & features — or [follow us on X](https://pris.ly/x)!**

##### Highlights

##### ORM

##### Tab completions for the Prisma CLI

Typing out CLI commands from memory is now optional. Prisma ships **shell tab completions** for `bash`, `zsh`, `fish`, and PowerShell, covering commands, subcommands, options, flags, and even option values.

**Setting it up.** Most projects run Prisma through a package manager, so completions are enabled through `@bomb.sh/tab`'s package-manager integration — install it once, then source the completion for your package manager and shell:

```bash

# 1. Install @&#8203;bomb.sh/tab globally
npm install -g @&#8203;bomb.sh/tab

# 2. Wire up your package manager + shell (pnpm shown; swap in npm / yarn / bun):
echo 'source <(tab pnpm zsh)'  >> ~/.zshrc            # zsh
echo 'source <(tab pnpm bash)' >> ~/.bashrc           # bash
tab pnpm fish > ~/.config/fish/completions/pnpm.fish  # fish
tab pnpm powershell > ~/.tab-pnpm.ps1                 # PowerShell (then dot-source it from $PROFILE)
```

`@bomb.sh/tab` delegates to any locally-installed CLI that ships completions, so `pnpm prisma <TAB>`, `pnpm exec prisma <TAB>`, `yarn prisma <TAB>`, and `bun x prisma <TAB>` all complete Prisma's commands, options, and values — no per-project setup. (`npx` and `bunx` don't support completion themselves; use `npm exec` and `bun x`.)

If instead you have Prisma installed globally on your `PATH`, source its own completion directly: `source <(prisma complete zsh)` (or the `bash` / `fish` / `powershell` variant).

This is built on [`@bomb.sh/tab`](https://github.com/bombshell-dev/tab/), the same completion library that powers other CLIs in the ecosystem — including Cloudflare, Nuxt, and Vitest — so the package-manager completions you enable for Prisma work for those tools too. A wonderful community contribution from [@&#8203;AmirSa12](https://github.com/AmirSa12) ([#&#8203;28351](prisma/orm#28351)) — thank you!

<https://github.com/user-attachments/assets/1f916a60-ee4d-40be-bb7d-74035d48ca83>

##### Prisma ORM, ready for AI agents

Coding agents are now a first-class audience for Prisma, and 7.9.0 brings the first wave of work to make Prisma projects safe and productive for them to work in.

**Agent skills installed with `prisma init`** ([#&#8203;29689](prisma/orm#29689))

`prisma init` now installs the [prisma/skills](https://github.com/prisma/skills) catalog into freshly scaffolded projects. Agents such as Claude Code, Cursor, Codex, and Windsurf start out with current, version-relevant Prisma knowledge instead of relying on whatever happened to be in their training data. The install is best-effort and never blocks scaffolding; opt out at any time with `--no-skills`.

```terminal
npx prisma@latest init
```

![prisma init scaffolds a project and installs the Prisma agent skills catalog](https://github.com/user-attachments/assets/8244a6dc-cdad-4028-a652-bb5ac6e4b271)

**A safer default around destructive commands** ([#&#8203;29684](prisma/orm#29684), [#&#8203;29691](prisma/orm#29691), [#&#8203;29713](prisma/orm#29713))

Prisma's AI safety checkpoint refuses to run destructive commands when it detects that an AI agent is at the keyboard, unless the user has given explicit consent. In this release we:

- **Broadened agent detection** to cover today's landscape — Codex CLI (now on Linux as well as macOS), Qwen Code, GitHub Copilot CLI, OpenCode, Cline, Goose, Amp, Crush, Augment Code, Antigravity, Replit Agent, and Devin — plus generic `AI_AGENT` / `AGENT` conventions so future agents are caught without a code change.
- **Extended the guard to `db push --accept-data-loss`**, which previously bypassed the checkpoint even though it can drop data.
- **Removed the `migrate-reset` tool from the `prisma mcp` server** entirely — resetting a database drops it, and that is not an operation an agent should be handed as a first-class tool. An agent that needs a reset must run the CLI, where the checkpoint applies.

##### Bug Fixes

Many of the fixes below are **community contributions** — thank you to everyone who reported and fixed these!

**Prisma Client**

- Fixed a severe TypeScript performance regression introduced in Prisma 7: restoring the `OmitOpts` generic default lets `tsc` reuse cached type instantiations again, bringing type-checking on large schemas back from minutes to seconds ([#&#8203;29592](prisma/orm#29592), from [@&#8203;nfl1ryxditimo12](https://github.com/nfl1ryxditimo12)).
- The `XOR` type helper now rejects primitive values such as `data: 5`, which were previously accepted at compile time even though the runtime rejected them ([#&#8203;29735](prisma/orm#29735), from [@&#8203;kyungseopk1m](https://github.com/kyungseopk1m)).
- `$queryRaw` and `$executeRaw` now fail fast with a clear validation error when passed an invalid `Date`, instead of silently serializing it as `null` and corrupting the value sent to the database ([#&#8203;29697](prisma/orm#29697), from [@&#8203;jibin7jose](https://github.com/jibin7jose)).
- The generated client is no longer corrupted by a `///` documentation comment that contains a `*/` sequence; the comment terminator is now escaped when doc comments are emitted, in both the TypeScript and JavaScript generators ([#&#8203;29736](prisma/orm#29736), from [@&#8203;kyungseopk1m](https://github.com/kyungseopk1m)).
- Improved the runtime and TypeScript error messages shown when a driver adapter is missing from the `PrismaClient` constructor; both now include a copy-pasteable example and a link to the [driver adapters docs](https://pris.ly/d/driver-adapters) ([#&#8203;29624](prisma/orm#29624)).
- Unmapped database errors from driver adapters now surface as a user-facing `P2039` (`PrismaClientKnownRequestError`) carrying the original code and message, instead of an opaque failure, which keeps schema-drift-style problems debuggable ([#&#8203;29512](prisma/orm#29512)).
- The `prisma-client-js` generator no longer emits a stray `undefined` statement when generating from a schema that declares only enums or types and no models ([#&#8203;29738](prisma/orm#29738), from [@&#8203;kyungseopk1m](https://github.com/kyungseopk1m)).
- Fixed a connection leak when an interactive transaction times out (`maxWait`) while it is still starting: the discarded transaction now sends an explicit `ROLLBACK` before the connection is returned to the pool, instead of releasing it mid-transaction. Previously, on adapters like `@prisma/adapter-pg` and `@prisma/adapter-neon`, the next query to reuse that connection could fail with `there is already a transaction in progress` — or silently commit the leaked transaction's work ([#&#8203;29727](prisma/orm#29727), from [@&#8203;lazerg](https://github.com/lazerg)).

**CLI**

- `prisma validate` (and other schema-loading commands) no longer hangs forever on a multi-file schema whose directories contain a symlink cycle, and no longer reports the same file twice when a directory is reachable under two spellings (e.g. `/tmp` → `/private/tmp` on macOS) ([#&#8203;29740](prisma/orm#29740), from [@&#8203;kyungseopk1m](https://github.com/kyungseopk1m)).
- On Windows, engine binaries are now cached in a stable, user-level directory (`%APPDATA%\Prisma`) instead of a `cwd`-relative `node_modules\.cache`, which eliminated duplicate cache directories and the bloated Serverless/Docker bundles they caused ([#&#8203;29730](prisma/orm#29730), from [@&#8203;santichausis](https://github.com/santichausis); closes [#&#8203;22574](prisma/orm#22574), [#&#8203;6670](prisma/orm#6670), [#&#8203;11577](prisma/orm#11577)).

**Driver Adapters**

- **[@&#8203;prisma/adapter-pg](https://github.com/prisma/adapter-pg)**, **[@&#8203;prisma/adapter-neon](https://github.com/prisma/adapter-neon)**, **[@&#8203;prisma/adapter-ppg](https://github.com/prisma/adapter-ppg)**: Reading a `Bytes` column no longer emits Node.js' `DEP0005` deprecation warning, thanks to an upstream `postgres-bytea` bump ([#&#8203;29538](prisma/orm#29538), from [@&#8203;kolia-zamnius](https://github.com/kolia-zamnius)).
- **[@&#8203;prisma/adapter-ppg](https://github.com/prisma/adapter-ppg)**: `ColumnNotFound` (`P2022`) errors now parse both quoted and unquoted PostgreSQL column names, including identifiers containing spaces, matching the fix previously applied to `adapter-pg` ([#&#8203;29737](prisma/orm#29737), from [@&#8203;kyungseopk1m](https://github.com/kyungseopk1m)).
- **[@&#8203;prisma/adapter-mssql](https://github.com/prisma/adapter-mssql)**: Setting a `Bytes?` (`@db.VarBinary`) field to `null` no longer fails with an implicit-conversion error; the adapter now sends the parameter typed as `VarBinary` instead of letting SQL Server default it to `nvarchar` ([#&#8203;29630](prisma/orm#29630), from [@&#8203;AnupamKumar-1](https://github.com/AnupamKumar-1)).

**Schema Engine**

- `prisma migrate status` now reports a rolled-back migration that still exists on disk as *unapplied*, instead of incorrectly treating the schema as up to date ([prisma/prisma-engines#5817](prisma/prisma-engines#5817), from [@&#8203;goutamadwant](https://github.com/goutamadwant)).
- Primary-key constraint renames are now rendered as separate `ALTER TABLE` statements on PostgreSQL, avoiding a database error when a single table has multiple changes in one migration ([prisma/prisma-engines#4906](prisma/prisma-engines#4906), from [@&#8203;eruditmorina](https://github.com/eruditmorina)).

##### Security

- Resolved the `hono` security advisories at their source: `@prisma/dev` was updated to a version that no longer depends on `hono` at all, so the CLI is no longer exposed to those advisories through that path. We also patched moderate-severity advisories in `ajv` and `uuid` across production dependencies ([#&#8203;29514](prisma/orm#29514)).
- Hardened the Prisma Platform credentials file (`~/.config/prisma-platform/auth.json`) and its directory to `0o600` / `0o700` so OAuth tokens are no longer world-readable, bringing Prisma in line with the GitHub, AWS, and Google Cloud CLIs ([#&#8203;29568](prisma/orm#29568), from Jaeyoung Yun).
- Bumped the `openssl` crate in the schema engine binaries from 0.10.74 to 0.10.81 ([prisma/prisma-engines#5815](prisma/prisma-engines#5815)).

##### Prisma Studio

The bundled Prisma Studio moves from `0.27.3` to `0.33.0` ([#&#8203;29720](prisma/orm#29720)), gathering up everything shipped in the Studio releases in between.

##### Migrations view

Studio can now visualise your **migration history**. This view is powered by **[Prisma Next](https://www.prisma.io/docs/orm/next)** — the next major version of Prisma ORM, a full TypeScript rewrite (available now in [Early Access](https://www.prisma.io/docs/next/getting-started)) that keeps the schema-first workflow and model-first queries you know, but treats your schema as a versioned, inspectable **contract** instead of compiling it into a heavy generated client. Prisma Next records every migration and its contract snapshots in the database, and Studio reads them to draw the timeline and diff below. Databases managed with classic Prisma Migrate don't carry this ledger, so the view simply stays hidden there.

When the connected database has a Prisma Next migration ledger, a **Migrations** entry appears in the sidebar: a newest-first timeline of every applied migration with its name, apply time, operation count, and compact chips summarizing what changed (`+2 models`, `~2 models +3 fields`, `+1 model`, …). Selecting a migration opens a visual, FigJam-style diff canvas — added, removed, and changed models as colour-coded cards (`NEW` / `UPDATED` / `UNCHANGED`) with per-field before → after details, enum cards, and relation edges — next to a SQL panel of the executed statements and a Prisma-schema line diff. Switching migrations morphs the canvas rather than rebuilding it.

![The Studio Migrations view: walking a Prisma Next migration history, the diff canvas morphing between migrations](https://github.com/user-attachments/assets/2633b77a-b1d9-4c3f-b5c4-c10908f040d9)

<!-- On publishing: drag wip/demos/prisma-studio-migrations.webp into the GitHub release editor so it becomes a user-attachments URL. -->

##### Prisma Streams browser

Studio gains first-class support for Prisma Streams: a dedicated stream browser, live stream aggregations, stream diagnostics, routing-key browsing, and a WAL-history handoff straight from your tables, plus richer stream request observability with concise event-log and OpenTelemetry span summaries.

##### Working with SQL

- SQL execution, linting, and navigation are now **schema-aware**: unqualified identifiers resolve against the schema you've selected instead of always falling back to the adapter's default schema.
- SQL result visualizations are rendered with Studio-owned chart configuration, and there's an optional **Queries** view backed by query-insights snapshots.
- Added copy actions to the Query Details view.

##### Fixes

- Fixed editing PostgreSQL text-array cells when queries are compiled with inline values.
- Avoided cancelling and repeating introspection requests when Studio first mounts, removing duplicate startup work.

##### Thanks to our contributors

A heartfelt thank you to the community members whose contributions shaped this release:

[@&#8203;AmirSa12](https://github.com/AmirSa12), [@&#8203;kyungseopk1m](https://github.com/kyungseopk1m), [@&#8203;nfl1ryxditimo12](https://github.com/nfl1ryxditimo12), [@&#8203;jibin7jose](https://github.com/jibin7jose), [@&#8203;santichausis](https://github.com/santichausis), [@&#8203;kolia-zamnius](https://github.com/kolia-zamnius), [@&#8203;goutamadwant](https://github.com/goutamadwant), [@&#8203;eruditmorina](https://github.com/eruditmorina), [@&#8203;lazerg](https://github.com/lazerg), [@&#8203;AnupamKumar-1](https://github.com/AnupamKumar-1), [@&#8203;Swapanrishi](https://github.com/Swapanrishi), [@&#8203;anupamme](https://github.com/anupamme), and [@&#8203;oyi77](https://github.com/oyi77).

##### Prisma Compute is now in public beta

**"Push code, it runs."** [Prisma Compute](https://www.prisma.io/compute) — managed hosting for TypeScript apps that run right next to your database — is now available in [public beta](https://blog.prisma.io/blog/launching-prisma-compute-public-beta), and free to use while the beta lasts.

Compute deploys your app as a long-lived process on Bun, colocated with your Prisma Postgres database, so there are no cold starts, no request timeouts, and no separate hosting vendor to wire up. It's a fit for REST and GraphQL APIs, full-stack apps, streaming and gRPC, and the long-running, stateful AI agents that keep connections open and hold in-process caches — "self-hosting, without the painful parts".

- **Push-to-deploy** from the CLI or via GitHub integration. Every deployment is an immutable, versioned release with its own preview URL, and rolling back is simply promoting a previous version.
- **Branch-based environments** — each branch gets its own app and database, so you can preview a change before promoting it to production.
- **Auto-wires with Prisma Postgres** (or bring any database), with automatic health checks and self-recovery.
- **[Custom domains](https://blog.prisma.io/blog/prisma-compute-custom-domains)** — point a single CNAME at Prisma and Compute provisions and renews the TLS certificate for you, with no manual certificate uploads or private-key handling.

With Prisma ORM for type-safe data access, Prisma Postgres for the managed database, and now Prisma Compute for hosting, the whole stack lives in one place. Read the full story in the [Prisma Compute blog series](https://blog.prisma.io/blog/series/prisma-compute).

##### Enterprise support

Thousands of teams use Prisma and many of them already tap into our Enterprise & Agency Support Program for hands-on help with everything from schema integrations and performance tuning to security and compliance.

With this program you also get priority issue triage and bug fixes, expert scalability advice, and custom training so that your Prisma-powered apps stay rock-solid at any scale. Learn more or join: <https://prisma.io/enterprise>.

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these updates again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNzIuMSIsInVwZGF0ZWRJblZlciI6IjQzLjI3Mi4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Reviewed-on: https://git.oirnoir.dev/OIRNOIR/YouTube-Helper-Server/pulls/30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants