fix(sentry): group Drizzle errors by underlying cause, not SQL text#2957
Merged
Conversation
Drizzle wraps query errors with a 'Failed query: <unique SQL>' message. beforeSend set a useful fingerprint, but the event's primary exception (used for the issue title) still carried the unique SQL string, so grouping regressed and the root cause (e.g. 'statement timeout') wasn't visible in the title. Rewrite the root exception value (last entry in event.exception.values, per Sentry's oldest-to-newest ordering) so its type/message reflect error.cause, and move the failed query + params into the drizzle_query context so they stay visible on the issue without polluting the title or fingerprint. Non-Drizzle errors and Drizzle errors without a cause are unaffected.
Contributor
Author
Code Review SummaryStatus: 1 Issues Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
Other Observations (not in diff)Issues found in unchanged code that cannot receive inline comments:
Files Reviewed (1 files)
Reviewed by gpt-5.5-20260423 · 224,613 tokens |
eshurakov
approved these changes
Apr 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fix Sentry grouping for Drizzle query errors in
apps/web/sentry.server.config.ts.The existing
beforeSendalready set a goodfingerprintfor Drizzle errors (based on the pg error code and cause message), but the reported event's primary exception was never modified — it still had Drizzle'sFailed query: <unique SQL>message. Sentry uses the last entry inevent.exception.valuesfor the issue title and as a grouping signal, so the title on every Drizzle-wrapped error was a unique SQL string and the actual root cause (e.g.statement timeout) wasn't visible at a glance.This PR rewrites the root exception value so its
typeandvaluereflecterror.cause(the underlying pg error), and moves the failed query + params into a newdrizzle_querycontext so the SQL remains visible on the issue without polluting the title or affecting grouping.Before
DrizzleQueryError: Failed query: SELECT … WHERE id = $1 …(unique per query site — breaks grouping)error.cause(real root cause, e.g.statement timeout) only surfaced via the fingerprint tuple and as a nested exception further down the chain.After
<CauseType>: canceling statement due to statement timeout(or whatevercause.message/cause.nameis) — stable across call sites.drizzle_querycontext, visible on the Sentry issue page.db.<op>()was called) is preserved — we only mutatetype/value, notstacktrace.fingerprintanddb.error_codetag behaviour is unchanged.causeare unaffected.Verification
apps/web/src/routers/admin/credit-campaigns-router.tsthat confirms Drizzle places the pg error (withcode,message) on.cause.pnpm typecheckper repo AGENTS guidance (full typecheck is too slow for targeted changes); ranpnpm format.Visual Changes
N/A — server-side Sentry reporting only.
Reviewer Notes
causeTypeNamehelper walkscause.name→cause.constructor.name→ falls back to'DatabaseError'. Drizzle's cause is typically apgDatabaseError, which has a meaningfulname, so the title will usually end up aserror: <pg message>orDatabaseError: <pg message>depending on how pg setsnamein the running version.event.contexts.drizzle_queryincludesparams. These are already covered by the existingnormalizeDepth: 5limit ininit, andbeforeSendruns after PII scrubbing integrations, so this matches the pre-existing treatment of query data in the issue payload (the SQL text was already reaching Sentry via the exception message).Built for Remon Oldenbeuving by Kilo for Slack