fix: resolve top Sentry issues (PPM-4, PPM-A, PPM-8)#136
Merged
mostafazh merged 2 commits intoJul 18, 2026
Conversation
The /api/gaza-status request in the landing page had no error handling: `fetch().then(res => res.json()).then(...)`. When the request fails (offline, ad-blocker, in-app browser, flaky network) the rejection is unhandled and reported to Sentry as "TypeError: Failed to fetch" (Chrome) or "TypeError: Load failed" (Safari), both via onunhandledrejection. The banner it feeds is non-essential, so failures should degrade silently. Add a `.catch()` and guard against a non-ok response so a failed request just logs and leaves the banner hidden instead of crashing out as an unhandled promise rejection. Fixes PPM-A Fixes PPM-8 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EbAFxseaTp5zr72vtKuBUo
Mobile users hit a hard crash reported to Sentry as "NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node" (PPM-4, the highest-volume issue). The stacktrace is React's commit phase (removeChild/insertBefore) recursing through the vendor chunk. This is the well-known React + browser-translation conflict: Google Translate / mobile-Chrome & in-app-browser auto-translate swap out the text nodes React is tracking, so when React later removes or reinserts one of them its parent has changed and the raw DOM call throws, taking down the whole app. The affected events are overwhelmingly non-English locales (Tunisia, Belgium, Germany, India) where auto-translate kicks in. Add a small client-only DomSafety patch, mounted from the root layout, that makes Node.prototype.removeChild / insertBefore no-op in exactly the case that would otherwise throw (node no longer under the expected parent). It only intercepts the throwing case, so valid DOM operations are unaffected. See react/react#11538. Fixes PPM-4 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EbAFxseaTp5zr72vtKuBUo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes the top Sentry issues in the ppm project (Tech For Palestine), taken from the highest-volume unresolved errors. These three issues account for ~70% of all captured error events (55 of 78).
Each fix is in its own commit.
Fixes
1.
PPM-4— ReactremoveChildcrash (46 events, the Top 1 issue)NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.The classic React + browser-translation conflict. Google Translate / mobile-Chrome & in-app-browser auto-translate replace the text nodes React is tracking; when React later removes or reinserts one, its parent has changed and the raw DOM call throws, crashing the whole app. Affected events are overwhelmingly non-English locales (Tunisia, Belgium, Germany, India) where auto-translate triggers.
Fix: a small client-only
DomSafetypatch (mounted from the root layout) that makesNode.prototype.removeChild/insertBeforeno-op only in the case that would otherwise throw. Well-formed DOM operations are untouched. See facebook/react#11538.2.
PPM-A+PPM-8— unhandled fetch rejection (6 + 3 events)TypeError: Load failed(Safari) /TypeError: Failed to fetch(Chrome), both viaonunhandledrejection.The
/api/gaza-statusfetch on the landing page had no error handling (fetch().then(res => res.json()).then(...)). A failed request (offline, ad-blocker, in-app browser, flaky network) became an unhandled promise rejection. Confirmed via matching app frame inpage.js— it's the only barefetchwithout a.catch().Fix: add a
.catch()and guard against a non-ok response. The banner it feeds is non-essential, so failures now degrade silently.Out of scope (deliberately not fixed here)
Maximum call stack size exceeded) — stack isundefined:31:70with no app frames; not confidently attributable to our code (likely an extension/injected script).NotFoundError: The object can not be found here.) — ambiguous DOM error; may be mitigated by the PPM-4 patch but not verified.window.webkit.messageHandlers,Java object is gone) — in-app-browser (WKWebView / Android WebView) injected-script noise, not our code. Better addressed via SentryignoreErrorsfiltering than a code change.Verification
npm run lint— 0 errors (1 pre-existing<img>warning, unrelated)tsc --noEmit— cleannpm run build— compiles,/prerenders (confirms the SSRNodeguard)npm test— 3/3 pass🤖 Generated with Claude Code