diff --git a/app/entry.server.tsx b/app/entry.server.tsx index 1bd0de74..29ede6a9 100644 --- a/app/entry.server.tsx +++ b/app/entry.server.tsx @@ -13,8 +13,16 @@ const sentryHandleError = Sentry.createSentryHandleError({ }) export const handleError: typeof sentryHandleError = (error, ctx) => { - // Skip reporting 404s to Sentry (bot/scanner noise) + // Skip react-router internal errors (bot/scanner 404s, missing-loader 400s) if (error instanceof Response && error.status === 404) return + if ( + error instanceof Error && + 'status' in error && + 'internal' in error && + ((error as { status: number }).status === 404 || + (error as { status: number }).status === 400) + ) + return sentryHandleError(error, ctx) } diff --git a/app/routes/api.github.webhook.ts b/app/routes/api.github.webhook.ts index b6395c49..42a85c5a 100644 --- a/app/routes/api.github.webhook.ts +++ b/app/routes/api.github.webhook.ts @@ -2,6 +2,10 @@ import { verifyWebhookSignature } from '~/app/libs/webhook-verify.server' import { processGithubWebhookPayload } from '~/app/services/github-webhook.server' import type { Route } from './+types/api.github.webhook' +export const loader = () => { + return new Response('Method Not Allowed', { status: 405 }) +} + export const action = async ({ request }: Route.ActionArgs) => { if (request.method !== 'POST') { return new Response('Method Not Allowed', { status: 405 }) diff --git a/instrument.server.mjs b/instrument.server.mjs index 9aa3ccf2..7270e06a 100644 --- a/instrument.server.mjs +++ b/instrument.server.mjs @@ -13,5 +13,18 @@ if (dsn) { dsn, sendDefaultPii: true, tracesSampleRate: parseSampleRate(process.env.SENTRY_TRACES_SAMPLE_RATE), + beforeSend(event) { + // Filter out react-router internal errors (404 bot/scanner noise, 400 missing loader) + const serialized = event.extra?.__serialized__ + if ( + serialized && + typeof serialized === 'object' && + serialized.internal === true && + (serialized.status === 404 || serialized.status === 400) + ) { + return null + } + return event + }, }) }