diff --git a/CHANGELOG.md b/CHANGELOG.md index 36b6ce2b..1078d410 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ and this project adheres to - 🐛(frontend) harden speaker test against missing sinks and play errors - 🐛(frontend) implement hysteresis band for the control bar layout - 🐛(frontend) fix toolbar ResizeObserver loop and alignment drift +- 🐛(analytics) filter benign ResizeObserver loop error in Sentry/PostHog ## [1.26.0] - 2026-08-12 diff --git a/src/frontend/src/features/analytics/exceptionFilters.ts b/src/frontend/src/features/analytics/exceptionFilters.ts new file mode 100644 index 00000000..9a11cfe9 --- /dev/null +++ b/src/frontend/src/features/analytics/exceptionFilters.ts @@ -0,0 +1,24 @@ +import type { CaptureResult } from 'posthog-js' + +const IGNORED_EXCEPTION_PATTERNS = [ + /ResizeObserver loop (completed with undelivered notifications|limit exceeded)/, +] + +const shouldIgnoreException = (value: unknown): boolean => + typeof value === 'string' && + IGNORED_EXCEPTION_PATTERNS.some((pattern) => pattern.test(value)) + +export const filterExceptions = ( + event: CaptureResult | null +): CaptureResult | null => { + if (event?.event !== '$exception') return event + + const exceptionList = event.properties?.['$exception_list'] + const values: unknown[] = Array.isArray(exceptionList) + ? exceptionList.map((exception) => exception?.value) + : [] + + values.push(event.properties?.['$exception_message']) + + return values.some(shouldIgnoreException) ? null : event +} diff --git a/src/frontend/src/features/analytics/hooks/useAnalytics.ts b/src/frontend/src/features/analytics/hooks/useAnalytics.ts index a1c2d372..1729bea2 100644 --- a/src/frontend/src/features/analytics/hooks/useAnalytics.ts +++ b/src/frontend/src/features/analytics/hooks/useAnalytics.ts @@ -2,6 +2,7 @@ import { useEffect } from 'react' import { type ApiUser } from '@/features/auth/api/ApiUser' import { useUser } from '@/features/auth/api/useUser' import { getPosthog } from '../utils' +import { filterExceptions } from '../exceptionFilters' export const startAnalyticsSession = (data: ApiUser) => { getPosthog().then((ph) => { @@ -47,6 +48,7 @@ export const useAnalytics = ({ capture_unhandled_rejections: true, capture_console_errors: true, }, + before_send: filterExceptions, }) }) }, [id, host, flags_api_host, isDisabled])