faro: extension-injected frames still classify as real app errors (follow-up to #4994)
Follow-up to #4994, which fixed three of the four ways a third-party Failed to fetch was reaching the real (app-bug) class in the Faro exception classifier.
The remaining case
hasProjectSourceFrame in src/utils/faro/classifyException.ts treats a browser-extension-injected frame as project source, so an exception originating entirely in an extension still classifies as real.
It is the whole class, not one browser — chrome-extension://, moz-extension:// and safari-web-extension:// all reach the bare-extension test the same way. A fix scoped to one scheme would leave the other two.
Size
Measured over ~1,000 live RUM beacons at the time #4994 was prepared: 314 / 957 (32.8%) of the context_error_category="real" population carried an extension-injected frame — roughly 2.1× the share #4994 itself removed. So this is the larger remaining contaminant.
Why it was deferred rather than folded into #4994
The natural fix routes through isInjectedFrame, which drives a DROP decision. Widening it therefore widens a drop path, and the classifier's stated safety posture is a conservative allowlist: anything unmatched falls through to real and is kept, because a false drop hides a real bug. That change deserves its own evidence and its own review rather than riding along with an unrelated fix.
Closing condition
A PR handling all three injected-extension schemes (chrome-extension://, moz-extension://, safari-web-extension://), graded by re-running the same beacon replay used for #4994 and showing the drop rate move.
Checked by: that PR merging to main with the before/after drop-rate measurement posted in its body.
Notes for whoever picks this up
- Keep the fail-open posture: prefer tagging over dropping if the evidence is ambiguous, so nothing is hidden from the data even when it is excluded from the actionable class.
- #4994 added a regression guard worth preserving:
@trpc/clientdispatches from asetTimeout, so a genuine first-party API failure carries no app frame and is kept only by an explicit API-client allowlist. Any widening of the injected-frame logic should be checked against that case — 183/957 (19.1%) of the population depended on it. - The test file is
src/utils/faro/__tests__/classifyException.test.ts; #4994's cases show the fixture shape, including realistic multi-frame stacks.
Source: civitai/civitai