Skip to content

Handle expected Prisma request errors - #1365

Merged
priosshrsth merged 3 commits into
mainfrom
cursor/OUT-3945-cursor-automated-triage-response-6a8f
Jul 2, 2026
Merged

Handle expected Prisma request errors#1365
priosshrsth merged 3 commits into
mainfrom
cursor/OUT-3945-cursor-automated-triage-response-6a8f

Conversation

@cursor

@cursor cursor Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Changes

  • Normalize expected Prisma known request errors in withErrorHandler:
    • P2025 record-not-found
    • P2023 invalid UUID
    • P2010 raw query failures caused by Postgres 22P02 invalid UUID casts
  • Avoid console.error for these controlled 4xx responses so they do not create noisy Sentry issues titled PrismaClientKnownRequestError:.
  • Keep logging for unclassified Prisma known request errors.
  • Add focused Jest coverage for the Prisma mappings and logging behavior.

Testing Criteria

  • yarn test src/app/api/tests/utils/withErrorHandler.test.ts --runInBand — 8 tests passed.
  • yarn prettier:check — passed.
  • yarn lint:check — passed with existing React hook/compiler warnings.
  • yarn tsc — blocked by pre-existing missing SVG module declarations in src/icons/index.ts before this change is typechecked.

Notes

  • Linear MCP returned 401 and Sentry MCP requires authentication, so direct event metadata could not be read from tools. The trigger metadata shows OUT-3945 in Triage, the title shape is Sentry-generated, and this repository is the Tasks app with Sentry configured for Tasks.

Impact & Surface Area of Change

  • Central API error handling for routes wrapped by withErrorHandler.
  • Expected invalid/not-found Prisma request failures now return the existing not-found response without noisy logging; unexpected Prisma known errors still log for follow-up.
Open in Web View Automation 

Co-authored-by: Neil Raina <makeitraina@users.noreply.github.com>
@linear-code

linear-code Bot commented Jul 1, 2026

Copy link
Copy Markdown

OUT-3945

@vercel

vercel Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
tasks-app Ready Ready Preview, Comment Jul 1, 2026 11:40am

Request Review

shouldLogError previously only logged >=500 or unclassified Prisma known
errors, so any unexpected error defaulting to 400 (plain Error, TypeError,
PrismaClientValidationError, etc.) was returned silently with no log — a
loss of Sentry visibility beyond the intended Prisma noise suppression.

Invert the check: log unless the error is a recognized expected client
error (Zod, Copilot, APIError, or a mapped Prisma known error). Add a test
covering an unexpected error still logging.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Deployment failed with the following error:

Deploying Serverless Functions to multiple regions is restricted to the Pro and Enterprise plans.

Learn More: https://vercel.link/multiple-function-regions

@priosshrsth

Copy link
Copy Markdown
Collaborator

Pushed a follow-up commit (becb7128) addressing a logging regression in shouldLogError.

Issue: the original check only logged when status >= 500 or the error was an unclassified PrismaClientKnownRequestError. Any genuinely unexpected error that defaults to a 400 — a plain Error/TypeError from a handler bug, PrismaClientValidationError, PrismaClientUnknownRequestError, etc. — would return silently with no log line, losing the Sentry visibility we most want on real bugs. That went beyond the intended goal of suppressing the expected Prisma 4xx noise.

Fix: inverted the logic to log unless the error is a recognized expected client error (Zod / Copilot / APIError / a mapped Prisma known error). Zod/Copilot/expected-Prisma stay quiet as intended; anything unrecognized still logs. Added a test asserting an unexpected Error still calls console.error.

All 9 tests pass (VERCEL_URL must be a scheme-qualified URL locally, e.g. http://localhost:3000).

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR refines the global withErrorHandler utility used by Next.js API routes to treat certain Prisma “known request errors” as expected client failures (returning consistent 404s) while reducing noisy console.error logging for those controlled 4xx responses (helping avoid Sentry noise).

Changes:

  • Refactored withErrorHandler to normalize errors via helper functions and conditionally log only unexpected/5xx cases.
  • Added Prisma known-request error mappings for P2025, P2023, and P2010 + Postgres 22P02 to return the existing “not found” response without logging.
  • Added Jest coverage to assert both the Prisma mappings and the logging/no-logging behavior across error classes.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/app/api/core/utils/withErrorHandler.ts Adds Prisma error normalization + conditional logging to reduce noise while preserving visibility for unexpected errors.
src/app/api/tests/utils/withErrorHandler.test.ts Adds focused unit tests validating Prisma error mapping and console.error behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@greptile-apps

greptile-apps Bot commented Jul 1, 2026

Copy link
Copy Markdown

Greptile Summary

This PR addresses a previous review concern about over-broad P2023 mapping by adding an isInvalidUuidError heuristic that only treats P2023 as a 404 when error.meta.message contains "uuid". It also extracts error normalization into focused helper functions and eliminates noisy console.error calls for expected 4xx Prisma errors.

  • P2023 narrowing: non-UUID P2023 errors (e.g. enum mismatches) now fall through to the unclassified path returning 400 with logging, rather than being silently hidden as 404.
  • Logging gate: shouldLogError suppresses console.error for ZodError, CopilotApiError, APIError, and the three handled Prisma codes, while still logging 5xx responses and unclassified errors.
  • Test coverage: 7 new test cases cover all Prisma paths including the P2023 non-UUID edge case, with a proper console.error spy lifecycle.

Confidence Score: 5/5

Safe to merge — the change narrows error classification, improves logging hygiene, and is fully covered by tests including the exact edge case flagged in the prior review.

All error-handling paths are exercised by the updated test suite, the P2023 concern from the prior review is resolved with a documented heuristic, and the refactored helpers are pure functions with no side effects. The only finding is an unreachable ternary branch that has no runtime impact.

No files require special attention.

Important Files Changed

Filename Overview
src/app/api/core/utils/withErrorHandler.ts Refactors error handling into pure helper functions; adds P2025/P2010+22P02/P2023-UUID → 404 mapping; suppresses console.error for expected client errors. Logic is correct; one dead ternary branch in the log line (ZodError.format() is unreachable).
src/app/api/tests/utils/withErrorHandler.test.ts Adds 7 new test cases covering all Prisma error paths and logging behaviour; console.error spy is correctly set up and torn down per-test. Tests are well-structured and cover the P2023 non-UUID edge case explicitly.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Error thrown in handler] --> B[normalizeError]
    B --> C{error type?}
    C -->|ZodError| D[422 UNPROCESSABLE_ENTITY\nfirst message string]
    C -->|CopilotApiError| E[error.status / error.body.message]
    C -->|APIError| F[error.status / error.message]
    C -->|PrismaClientKnownRequestError| G{getPrismaKnownRequestErrorResponse}
    C -->|other| H[400 BAD_REQUEST\n'Something went wrong']
    G -->|P2025| I[404 NOT_FOUND]
    G -->|P2010 + meta.code==22P02| I
    G -->|P2023 + meta.message contains 'uuid'| I
    G -->|null - unclassified| H
    D --> J[shouldLogError?]
    E --> J
    F --> J
    I --> J
    H --> J
    J -->|status >= 500| K[console.error]
    J -->|not isExpectedClientError| K
    J -->|isExpectedClientError + status < 500| L[silent]
    K --> M[NextResponse.json]
    L --> M
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[Error thrown in handler] --> B[normalizeError]
    B --> C{error type?}
    C -->|ZodError| D[422 UNPROCESSABLE_ENTITY\nfirst message string]
    C -->|CopilotApiError| E[error.status / error.body.message]
    C -->|APIError| F[error.status / error.message]
    C -->|PrismaClientKnownRequestError| G{getPrismaKnownRequestErrorResponse}
    C -->|other| H[400 BAD_REQUEST\n'Something went wrong']
    G -->|P2025| I[404 NOT_FOUND]
    G -->|P2010 + meta.code==22P02| I
    G -->|P2023 + meta.message contains 'uuid'| I
    G -->|null - unclassified| H
    D --> J[shouldLogError?]
    E --> J
    F --> J
    I --> J
    H --> J
    J -->|status >= 500| K[console.error]
    J -->|not isExpectedClientError| K
    J -->|isExpectedClientError + status < 500| L[silent]
    K --> M[NextResponse.json]
    L --> M
Loading

Reviews (2): Last reviewed commit: "fix(errors): narrow Prisma P2023 mapping..." | Re-trigger Greptile

Comment thread src/app/api/core/utils/withErrorHandler.ts Outdated
Greptile flagged that blanket-mapping P2023 ("Inconsistent column data")
to 404 could silently misclassify non-UUID column errors (e.g. enum
mismatches) as not-found and suppress their logging.

Only treat P2023 as not-found when the meta message indicates a malformed
UUID; other P2023 errors now fall through to the unclassified path (400 +
logged). Add a test asserting a non-UUID P2023 stays a logged 400.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@priosshrsth

Copy link
Copy Markdown
Collaborator

@greptileai review

Addressed the P2023 concern from the last review (commit 4ffcf27f).

Concern: P2023 ("Inconsistent column data") was blanket-mapped to 404, which could silently misclassify non-UUID column errors (e.g. enum mismatches) as not-found and suppress their logging.

Fix: P2023 is now only treated as 404 when error.meta.message indicates a malformed UUID (isInvalidUuidError). Any other P2023 falls through to the unclassified path — 400 + logged — so it stays visible. P2010+22P02 and P2025 are unchanged.

Added a test (logs non-UUID Prisma P2023 errors instead of hiding them as 404) asserting an enum-style P2023 returns 400 and calls console.error. All 10 tests pass.

@SandipBajracharya SandipBajracharya left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lgtm

@priosshrsth
priosshrsth merged commit 286b1ef into main Jul 2, 2026
4 checks passed
priosshrsth added a commit that referenced this pull request Jul 2, 2026
* Handle expected Prisma request errors (#1365)
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.

4 participants