Skip to content

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

Description

@larryro

Problem

Any Convex call that fails repeatedly in the browser floods GlitchTip with one issue per event instead of one issue with N events. Concrete case: the deleted-org incident #3019 minted 100+ single-event issues between 2026-07-18 and 08-11 — roughly a third of the demo project's total issue count at the time (100+ of 327) — all shaped like:

[CONVEX A(agents/file_actions:listAgents)] [Request ID: 5dabf348f1164725] Server Error
[CONVEX A(providers/file_actions:listProviders)] [Request ID: 91c0…] Server Error
[CONVEX A(branding/file_actions:readBranding)] [Request ID: …] Server Error

Noise at that volume buries real regressions — the #3019 incident itself sat unnoticed in that pile for a month.

Why

  1. convex/react logs every failed query/action via console.error('[CONVEX A(module:fn)] [Request ID: xxxx] Server Error …');
  2. Sentry.captureConsoleIntegration({ levels: ['error'] }) promotes each such call to an event (app/router.tsx:90);
  3. Sentry.init (app/router.tsx:81-94) has no beforeSend, no ignoreErrors, no fingerprint configuration;
  4. the [Request ID: …] embedded in the message is unique per call, so message-based grouping never matches → a brand-new GlitchTip issue every time.

Nothing about this is specific to deleted orgs: any recurring browser-side Convex failure keeps minting issues at event rate until this is fixed.

Suggested

Add a beforeSend that fingerprints console-captured Convex errors on the message minus the Request ID, and optionally drops codes the client already handles terminally (the server-side report for those exists anyway). Sketch to adjust:

beforeSend(event) {
  const msg = event.message ?? event.exception?.values?.[0]?.value ?? '';
  const convex = msg.match(/^\[CONVEX [QMA]\([^)]+\)\]/);
  if (convex) {
    // The Request ID is unique per call — strip it or grouping never matches.
    event.fingerprint = [msg.replace(/\[Request ID: [^\]]+\]\s*/, '').slice(0, 200)];
    // Optional: expected, client-handled outcomes add no signal as browser events.
    if (/ORG_NOT_FOUND|ORG_FORBIDDEN|UNAUTHENTICATED/.test(msg)) return null;
  }
  return event;
}

(Verify whether captureConsoleIntegration puts the text on event.message or event.logentry for the SDK version in use before shipping.)

Verifying

After deploy, trigger the same failing call twice from a browser (e.g. a garbage org id against a public query) and confirm GlitchTip shows one issue with 2 events rather than two issues. Then bulk-resolve the existing single-event backlog (see the cleanup checklist in #3019).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions