Skip to content

fix(platform): group browser Sentry events for repeated Convex errors - #3027

Open
larryro wants to merge 1 commit into
mainfrom
fix/sentry-convex-console-grouping
Open

fix(platform): group browser Sentry events for repeated Convex errors#3027
larryro wants to merge 1 commit into
mainfrom
fix/sentry-convex-console-grouping

Conversation

@larryro

@larryro larryro commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Any Convex call that fails repeatedly in the browser floods GlitchTip with one issue per event: convex/react logs every failure as console.error('[CONVEX A(module:fn)] [Request ID: <unique>] …'), captureConsoleIntegration promotes each line to an event, and Sentry.init had no beforeSend / fingerprint — so the per-call Request ID defeats message grouping every single time. Concrete cost: the deleted-org incident #3019 minted 100+ single-event issues (roughly a third of the demo project's total at review time), and the incident itself sat unnoticed in that pile for a month. Nothing about this is org-specific — any recurring browser-side failure keeps minting issues at event rate until grouping works.

Fixes #3020.

What changed

New app/lib/sentry/convex-console-events.ts, wired as beforeSend in app/router.tsx:

  • Group by what failed, not which request failed first. For [CONVEX Q|M|A(…)] lines the Request ID is stripped out of the message and the event is fingerprinted on the stripped text (capped at 200 chars). Rewriting the message too means the events group even where custom fingerprints aren't honoured, and issue titles stop embedding a random id.
  • Nothing is lost. The id survives as a searchable convex.request_id tag, and captureConsoleIntegration already preserves the raw console arguments in extra.arguments (verified against @sentry/core 10.x sources: string-only console args go through captureMessageevent.message).
  • Console copies of client-handled outcomes are dropped. ORG_NOT_FOUND / ORG_FORBIDDEN (the dashboard bounces the tab) and UNAUTHENTICATED (the session-rotation window the layout boundary deliberately retries, Bug: workflow execution mutations/actions throw raw Error — execution management rejections are opaque Server Errors #2013) return null — the recovery is the feature, and the server-side report of the same failure exists anyway. Dropping applies only to logger: 'console' events: an error that actually reached a boundary is real user impact and is kept, just normalized the same way (its exception value is cleaned and fingerprinted).
  • Foreign events pass through untouched.

Risk

beforeSend runs on every browser event, so the helper is deliberately anchored (^\[CONVEX …) and allocation-light; non-Convex events take two cheap checks and exit. The drop-list is three exact codes the app demonstrably handles (dashboard/index.tsx / $id.tsx bounce; use-action-query.ts treats structured ConvexErrors as terminal). Server-side visibility of those failures is unchanged — Convex backend reporting is a separate pipeline.

Tests

app/lib/sentry/convex-console-events.test.ts: two occurrences of one failure get the same fingerprint AND message with their ids preserved as tags; each handled code's console copy is dropped; a boundary exception with a handled code is kept but normalized; foreign message/exception events pass through untouched; the raw normalizer strips/returns the id and rejects non-Convex text.

Verifying after deploy

Trigger the same failing call twice from a browser (e.g. a garbage org id against a public action) and confirm GlitchTip shows one issue with 2 events rather than two issues. Then bulk-resolve the single-event backlog per the checklist in #3019.

Related: #3019 (incident), sibling PRs for #3019/#3021/#3022.

Gate: tsc --noEmit clean, oxlint --type-aware clean, oxfmt, vitest 9 passed.

convex/react logs every failed call with a per-call [Request ID: …] in
the message, and captureConsoleIntegration promotes each line to an
event with no beforeSend/fingerprint configured — so a recurring failure
minted one GlitchTip issue PER EVENT (100+ single-event issues during
the deleted-org incident, a third of the demo project's total) and real
regressions drowned.

beforeSend now strips the Request ID out of Convex client lines and
fingerprints on the stripped text; the id survives as a searchable
convex.request_id tag and the raw console args in extra.arguments.
Console copies of outcomes the client handles terminally (ORG_NOT_FOUND
/ ORG_FORBIDDEN bounce, UNAUTHENTICATED session-rotation retry) are
dropped — the server-side report exists; errors that reached a boundary
are kept and grouped the same way.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

improvement Improvement service: platform Platform service

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improvement: browser Sentry events never group — convex/react's "[Request ID: …]" in console.error makes every failure a new GlitchTip issue

1 participant