diff --git a/sentry.edge.config.ts b/sentry.edge.config.ts index 6bdf1ca44..2317ad991 100644 --- a/sentry.edge.config.ts +++ b/sentry.edge.config.ts @@ -4,6 +4,7 @@ // https://docs.sentry.io/platforms/javascript/guides/nextjs/ import * as Sentry from '@sentry/nextjs' +import { sentryIgnoreErrors } from './src/utils/sentryIgnoreErrors' const dsn = process.env.NEXT_PUBLIC_SENTRY_DSN || process.env.SENTRY_DSN @@ -16,5 +17,7 @@ if (dsn) { // Setting this option to true will print useful information to the console while you're setting up Sentry. debug: false, + + ignoreErrors: sentryIgnoreErrors, }) } diff --git a/sentry.server.config.ts b/sentry.server.config.ts index 80a781ce6..66490a0be 100644 --- a/sentry.server.config.ts +++ b/sentry.server.config.ts @@ -3,6 +3,7 @@ // https://docs.sentry.io/platforms/javascript/guides/nextjs/ import * as Sentry from '@sentry/nextjs' +import { sentryIgnoreErrors } from './src/utils/sentryIgnoreErrors' const dsn = process.env.NEXT_PUBLIC_SENTRY_DSN || process.env.SENTRY_DSN const vercelEnv = process.env.NEXT_PUBLIC_VERCEL_ENV @@ -20,7 +21,7 @@ if (dsn) { // Uncomment the line below to enable Spotlight (https://spotlightjs.com) // spotlight: process.env.NODE_ENV === 'development', - ignoreErrors: [/fetch failed/i, /failed to fetch/i], + ignoreErrors: sentryIgnoreErrors, beforeSend(event) { if (!isProd && event.type === undefined) { diff --git a/src/instrumentation-client.ts b/src/instrumentation-client.ts index 0cb7aefe3..b54bdc621 100644 --- a/src/instrumentation-client.ts +++ b/src/instrumentation-client.ts @@ -3,6 +3,7 @@ // https://docs.sentry.io/platforms/javascript/guides/nextjs/ import * as Sentry from '@sentry/nextjs' +import { sentryIgnoreErrors } from '@/utils/sentryIgnoreErrors' const dsn = process.env.NEXT_PUBLIC_SENTRY_DSN || process.env.SENTRY_DSN const vercelEnv = process.env.NEXT_PUBLIC_VERCEL_ENV @@ -33,7 +34,7 @@ if (dsn) { // }), ], - ignoreErrors: [/fetch failed/i, /failed to fetch/i], + ignoreErrors: sentryIgnoreErrors, beforeSend(event) { if (!isProd && event.type === undefined) { diff --git a/src/jobs/sentry.ts b/src/jobs/sentry.ts index 3e3c5a050..be1976149 100644 --- a/src/jobs/sentry.ts +++ b/src/jobs/sentry.ts @@ -1,6 +1,7 @@ import 'server-only' import * as Sentry from '@sentry/nextjs' +import { sentryIgnoreErrors } from '@/utils/sentryIgnoreErrors' // Trigger.dev runs jobs in a standalone Node process, separate from the Next.js server, so // `sentry.server.config.ts` (loaded via instrumentation.ts) never executes here — without @@ -17,7 +18,7 @@ if (dsn) { // integration set (matches Trigger.dev's documented Sentry setup). defaultIntegrations: false, environment: process.env.SENTRY_ENVIRONMENT || process.env.NODE_ENV || 'development', - ignoreErrors: [/fetch failed/i], + ignoreErrors: sentryIgnoreErrors, }) } diff --git a/src/utils/sentryIgnoreErrors.test.ts b/src/utils/sentryIgnoreErrors.test.ts new file mode 100644 index 000000000..8c84d6e6b --- /dev/null +++ b/src/utils/sentryIgnoreErrors.test.ts @@ -0,0 +1,17 @@ +import { sentryIgnoreErrors } from './sentryIgnoreErrors' + +const isIgnored = (message: string) => sentryIgnoreErrors.some((pattern) => pattern.test(message)) + +describe('sentryIgnoreErrors', () => { + it.each([ + 'retryable error: max retries exceeded', + 'Unable to send replay - max retries exceeded', + 'TypeError: fetch failed', + ])('ignores known retry and network noise: %s', (message) => { + expect(isIgnored(message)).toBe(true) + }) + + it('does not ignore application errors', () => { + expect(isIgnored('Failed to perform a Copilot API call: {"code":"api_error"}')).toBe(false) + }) +}) diff --git a/src/utils/sentryIgnoreErrors.ts b/src/utils/sentryIgnoreErrors.ts new file mode 100644 index 000000000..e09f19236 --- /dev/null +++ b/src/utils/sentryIgnoreErrors.ts @@ -0,0 +1,6 @@ +export const sentryIgnoreErrors = [ + /fetch failed/i, + /failed to fetch/i, + /retryable error: max retries exceeded/i, + /unable to send replay - max retries exceeded/i, +]