fix: don't autocapture PostHog's own network errors in react-native#3665
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Size Change: +501 B (0%) Total Size: 16.4 MB
ℹ️ View Unchanged
|
Prompt To Fix All With AIFix the following 2 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 2
packages/react-native/test/error-tracking-internal-errors.integration.spec.ts:33-43
**Missing assertion that `caught` is actually defined**
If `posthog.flush()` resolves (rather than rejects) — for example if the core swallows the `PostHogFetchNetworkError` internally before propagating — `caught` stays `undefined`. `isPostHogFetchNetworkError(undefined)` returns `false`, so the test fails with `Expected: true, Received: false`, with no indication that flush never threw. An explicit `expect(caught).toBeDefined()` between the `try/catch` and the guard assertion would surface the real problem immediately.
### Issue 2 of 2
packages/react-native/test/error-tracking-internal-errors.spec.ts:34-70
**Prefer parameterised tests**
The two "does not capture a network error" cases (uncaught-exception handler and unhandled-rejection handler) share the same assertion and only differ in the `ErrorTracking` constructor options and the mock call index used to retrieve the handler. These could be collapsed into a single `it.each` table, which is the preferred pattern in this codebase and eliminates the repeated `mockReturnValue(true)` + `handler(new Error('network'))` + `expect(mockPostHog.capture).not.toHaveBeenCalled()` sequence.
Reviews (1): Last reviewed commit: "fix: don't autocapture PostHog's own net..." | Re-trigger Greptile |
| } | ||
|
|
||
| // Offline/timeout failures are expected, not application errors. | ||
| if (isPostHogFetchNetworkError(error)) { |
There was a problem hiding this comment.
should we use isPostHogFetchError instead and also do not capture 4xx and 5xx fetch errors for the posthog API?
There was a problem hiding this comment.
5xx could make sense, but my thinking was that 4xx is probably a misconfig error that we should surface to the developers? Not strictly an application error, but not something expected as a connectivity error either. Since both are not expected to surface that often, I chose to keep them but I don't have a strong opinion on this tbh
There was a problem hiding this comment.
the way i see is 'is this error actionable, can i do something about it?'
for 4xx errors and 5xx errors, most likely the answer is always yes
what i am worried about is if we are entering an endless loop here
we capture an event/or error, API is 400..500, API throws, we capture the error again, and thats how we flood the server and waste cycles in the client
There was a problem hiding this comment.
most likely @PostHog/team-error-tracking would have opinions here, and if we decide not to capture our own errors, we have to revisit this in all SDKs
There was a problem hiding this comment.
Agreed, I'll merge this one to unblock the user though and we can revisit with a followup PR based on the discussion here
There was a problem hiding this comment.
Seems like posthog-js is pretty bulletproof when it comes to handling errors produced by us. All stuff like fetch errors are gated behind catches. And then in the whole error tracking pipeline we made sure not to throw unhandled errors (we've had these cases before). I'll look at other SDKs tho
marandaneto
left a comment
There was a problem hiding this comment.
left one comment (suggestion) and one question, not a blocker, LGTM otherwise
the bot has comments as well
Problem
Closes #3664
React Native / Expo apps with error-tracking autocapture enabled were seeing their dashboards flooded with
PostHogFetchNetworkErrorevents. This is PostHog's own internal error — thrown by the core when afetchfails to reach the server (device offline or request timeout). It's an expected, non-actionable connectivity condition, not an application error, but the autocapture handlers reported it as a$exception.The leak path: a user (or auto-flush) calls into the SDK, the network request fails offline, and the resulting
PostHogFetchNetworkErrorsurfaces as an uncaught exception / unhandled rejection — which the error-tracking handlers then capture and send.Changes
@posthog/core: export a newisPostHogFetchNetworkError(err): err is PostHogFetchNetworkErrortype guard (instanceof-based). The error class itself stays module-private; only the guard is public surface.posthog-react-native: theonUncaughtExceptionandonUnhandledRejectionautocapture handlers now skip errors matching the guard. The console autocapture path is intentionally left untouched, andPostHogFetchHttpError(bad API key, 5xx, etc.) is intentionally not filtered — those are developer-actionable and should remain visible.PostHogFetchNetworkErrorthrough core's real fetch path and verifies the guard recognizes it. Extracted sharedcreateMockPostHog()/createMockLogger()intotest-utils.ts.Scope was deliberately limited to network errors only (not all PostHog-internal errors) to preserve visibility of misconfiguration errors like a bad API key.
Release info Sub-libraries affected
Libraries affected
Checklist
If releasing new changes
pnpm changesetto generate a changeset file