Third-Party Noise Suppression
Suppress unactionable third-party SDK noise at the observability layer, not at the call site. Source: apps/website/providers/posthog-provider.tsx (Dedalus monorepo)
Third-party SDKs routinely throw unhandled promise rejections from their own internal fetch calls - analytics retries, ad-pixel beacons, Stripe Radar's hCaptcha attachment, intercom heartbeat pings. These pollute exception inboxes without being actionable. The fix is to filter them at the observability boundary, not by wrapping every SDK call in try/catch.
Why Call-Site try/catch Fails
When you await someSdk.doThing() and the SDK fires a side-effect fetch after the awaited promise resolves, the rejection happens asynchronously, after your wrapper has returned. The try/catch catches nothing. The rejection becomes a window.onunhandledrejection event and gets forwarded to PostHog, Sentry, or Datadog by their autocapture handlers.
The SDK author owns the root cause. You only own the boundary.
The Filter Pattern
Every observability SDK exposes a pre-send hook for exactly this case:
| Tool | Hook | Returns to drop |
|---|---|---|
| PostHog | before_send |
null |
| Sentry | beforeSend |
null |
| Datadog RUM | beforeSend |
false |
Filter by URL substring + exception type, not by error type alone. A blanket FetchError filter hides real bugs. A narrow URL match (api.stripe.com/v1/radar/session/.../attach_hcaptcha) targets only the known-unactionable noise and lets legitimate Stripe errors surface.
When to Suppress vs. Fix
This rule does not contradict [[empirical-verification]]. Verify the noise is actually unactionable before suppressing:
- You own the root cause - fix it. Suppression is hiding evidence.
- A third party owns the root cause AND the SDK already handles it gracefully - suppress at the boundary with a comment explaining what's noise and why.
- A third party owns the root cause AND breaks user-facing functionality - file a bug upstream, suppress the noise, and add a banner or fallback for users.
The suppression code must explain what is being dropped, why it's unactionable, and what we'd see if the noise pattern stops matching real-world events. Future readers should be able to delete the filter when the upstream SDK fixes its housekeeping.
Reference Incident
May 2026: Stripe.js's stripe.createRadarSession() fires POST https://api.stripe.com/v1/radar/session/<id>/attach_hcaptcha_token for Radar fingerprinting. On Safari and Mobile Safari, ITP and content blockers kill the request. Stripe.js converts the failure to an unhandled FetchError. The Radar session ID still resolves, so fingerprinting works - only the auxiliary hCaptcha signal is missing.
PostHog's autocapture surfaced 4 occurrences in 7 days from real users, all on Safari, none correlated with payment failures. Fix: a narrow before_send filter in apps/website/providers/posthog-provider.tsx that drops events where $exception_list[].value matches both api.stripe.com/v1/radar/session and attach_hcaptcha.
Concept Position
| Field | Value |
|---|---|
| Concept family | Agent harness and runtime primitives |
| Concept owned | Suppress unactionable third-party SDK noise at the observability layer, not at the call site. Source: apps/website/providers/posthog-provi... |
| Category map | Concept System Map |
Timeline
- 2026-07-01 | Concepts category refresh added this page to the Agent harness and runtime primitives family, linked it to Concept System Map, and kept it standalone because it owns this reusable mental model: Suppress unactionable third-party SDK noise at the observability layer, not at the call site. [Source: apps/website/providers/posthog-provi... [Source: User request, 2026-07-01