From 9b4f0ab4222f89e7b7dc3a75599527f54ef1d1c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Falc=C3=B3n?= Date: Thu, 14 May 2026 14:58:20 +0100 Subject: [PATCH] Filter Facebook webview bridge errors (#401) ## Summary - drop Facebook Android in-app browser Java bridge shutdown errors - require the iabjs navigation performance logger frame so app errors still report Fixes PHP-LARAVEL-20 Fixes PHP-LARAVEL-1Y ## Tests - npm run test -- resources/js/lib/sentry.test.ts - npm run lint -- resources/js/app.tsx resources/js/lib/sentry.ts resources/js/lib/sentry.test.ts *(passes with existing chart hook warning)* --- resources/js/app.tsx | 4 ++- resources/js/lib/sentry.test.ts | 55 ++++++++++++++++++++++++++++++++- resources/js/lib/sentry.ts | 22 +++++++++++++ 3 files changed, 79 insertions(+), 2 deletions(-) diff --git a/resources/js/app.tsx b/resources/js/app.tsx index 66f6881b..c0125d58 100644 --- a/resources/js/app.tsx +++ b/resources/js/app.tsx @@ -23,6 +23,7 @@ import { installChunkLoadRecovery } from './lib/chunk-load-recovery'; import { initializePostHog } from './lib/posthog'; import { isChunkLoadErrorEvent, + isFacebookInAppBrowserJavaBridgeNoise, isPostMessageDataCloneNoise, } from './lib/sentry'; import type { SharedData } from './types'; @@ -39,7 +40,8 @@ Sentry.init({ beforeSend(event) { if ( isChunkLoadErrorEvent(event) || - isPostMessageDataCloneNoise(event) + isPostMessageDataCloneNoise(event) || + isFacebookInAppBrowserJavaBridgeNoise(event) ) { return null; } diff --git a/resources/js/lib/sentry.test.ts b/resources/js/lib/sentry.test.ts index 504a4e26..91596eb8 100644 --- a/resources/js/lib/sentry.test.ts +++ b/resources/js/lib/sentry.test.ts @@ -1,6 +1,10 @@ import type { Event } from '@sentry/react'; import { describe, expect, it } from 'vitest'; -import { isChunkLoadErrorEvent, isPostMessageDataCloneNoise } from './sentry'; +import { + isChunkLoadErrorEvent, + isFacebookInAppBrowserJavaBridgeNoise, + isPostMessageDataCloneNoise, +} from './sentry'; describe('isChunkLoadErrorEvent', () => { it('drops recoverable Vite dynamic import failures', () => { @@ -34,6 +38,55 @@ describe('isChunkLoadErrorEvent', () => { }); }); +describe('isFacebookInAppBrowserJavaBridgeNoise', () => { + it('drops Facebook Android webview Java bridge shutdown errors', () => { + const event: Event = { + exception: { + values: [ + { + type: 'Error', + value: 'Error invoking postMessage: Java object is gone', + stacktrace: { + frames: [ + { + filename: + 'iabjs://navigation_performance_logger_android', + function: 'U', + }, + ], + }, + }, + ], + }, + }; + + expect(isFacebookInAppBrowserJavaBridgeNoise(event)).toBe(true); + }); + + it('keeps matching messages without the Facebook webview frame', () => { + const event: Event = { + exception: { + values: [ + { + type: 'Error', + value: 'Error invoking postMessage: Java object is gone', + stacktrace: { + frames: [ + { + filename: '/build/assets/app.js', + function: 'postMessage', + }, + ], + }, + }, + ], + }, + }; + + expect(isFacebookInAppBrowserJavaBridgeNoise(event)).toBe(false); + }); +}); + describe('isPostMessageDataCloneNoise', () => { it('drops browser postMessage DataCloneError noise', () => { const event: Event = { diff --git a/resources/js/lib/sentry.ts b/resources/js/lib/sentry.ts index 54a90845..aac1f5f1 100644 --- a/resources/js/lib/sentry.ts +++ b/resources/js/lib/sentry.ts @@ -3,6 +3,8 @@ import { isChunkLoadError } from './chunk-load-recovery'; const CLONE_ERROR_MESSAGE_PATTERN = /object (can not|could not|couldn't|can't) be cloned/i; +const FACEBOOK_IAB_JAVA_OBJECT_GONE_PATTERN = + /Error invoking .+: Java object is gone/i; export function isChunkLoadErrorEvent(event: Event): boolean { return ( @@ -33,3 +35,23 @@ export function isPostMessageDataCloneNoise(event: Event): boolean { }) ?? false ); } + +export function isFacebookInAppBrowserJavaBridgeNoise(event: Event): boolean { + return ( + event.exception?.values?.some((exception) => { + const exceptionValue = exception.value ?? ''; + const frames = exception.stacktrace?.frames ?? []; + + return ( + FACEBOOK_IAB_JAVA_OBJECT_GONE_PATTERN.test(exceptionValue) && + frames.some((frame) => + [frame.filename, frame.module].some((value) => + value?.includes( + 'iabjs://navigation_performance_logger_android', + ), + ), + ) + ); + }) ?? false + ); +}