Skip to content

fix(browser): Fix internal frame detection in minified bundles#20802

Open
chargome wants to merge 2 commits into
developfrom
cg/third-p-minified
Open

fix(browser): Fix internal frame detection in minified bundles#20802
chargome wants to merge 2 commits into
developfrom
cg/third-p-minified

Conversation

@chargome
Copy link
Copy Markdown
Member

The ignoreSentryInternalFrames option in thirdPartyErrorFilterIntegration relied on source-code-level signals (filename, context_line, comment patterns) that are all lost after minification.

This PR adds a runtime depth counter (GLOBAL_OBJ._sentryWrappedDepth) that tracks whether processEvent is running inside a sentryWrapped call. This works regardless of minification and also covers framework-caught errors (e.g. Vue swallowing the error before sentryWrapped's catch fires).

closes #20687

@chargome chargome self-assigned this May 11, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 11, 2026

size-limit report 📦

Path Size % Change Change
@sentry/browser 26.39 kB +0.08% +20 B 🔺
@sentry/browser - with treeshaking flags 24.83 kB +0.07% +15 B 🔺
@sentry/browser (incl. Tracing) 44.27 kB +0.07% +30 B 🔺
@sentry/browser (incl. Tracing + Span Streaming) 46.49 kB +0.06% +25 B 🔺
@sentry/browser (incl. Tracing, Profiling) 49.25 kB +0.07% +31 B 🔺
@sentry/browser (incl. Tracing, Replay) 83.88 kB +0.03% +22 B 🔺
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 73.34 kB +0.04% +22 B 🔺
@sentry/browser (incl. Tracing, Replay with Canvas) 88.57 kB +0.03% +24 B 🔺
@sentry/browser (incl. Tracing, Replay, Feedback) 101.21 kB +0.03% +23 B 🔺
@sentry/browser (incl. Feedback) 43.55 kB +0.06% +22 B 🔺
@sentry/browser (incl. sendFeedback) 31.21 kB +0.07% +20 B 🔺
@sentry/browser (incl. FeedbackAsync) 36.3 kB +0.06% +21 B 🔺
@sentry/browser (incl. Metrics) 27.67 kB +0.1% +25 B 🔺
@sentry/browser (incl. Logs) 27.8 kB +0.09% +23 B 🔺
@sentry/browser (incl. Metrics & Logs) 28.5 kB +0.1% +28 B 🔺
@sentry/react 28.13 kB +0.1% +26 B 🔺
@sentry/react (incl. Tracing) 46.52 kB +0.07% +29 B 🔺
@sentry/vue 31.28 kB +0.13% +38 B 🔺
@sentry/vue (incl. Tracing) 46.14 kB +0.11% +50 B 🔺
@sentry/svelte 26.41 kB +0.07% +17 B 🔺
CDN Bundle 28.96 kB +0.04% +11 B 🔺
CDN Bundle (incl. Tracing) 46.98 kB +0.05% +19 B 🔺
CDN Bundle (incl. Logs, Metrics) 30.37 kB +0.05% +15 B 🔺
CDN Bundle (incl. Tracing, Logs, Metrics) 48.1 kB +0.04% +18 B 🔺
CDN Bundle (incl. Replay, Logs, Metrics) 69.7 kB +0.03% +17 B 🔺
CDN Bundle (incl. Tracing, Replay) 84.38 kB +0.02% +12 B 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 85.43 kB +0.01% +7 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) 90.18 kB +0.03% +21 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 91.28 kB +0.03% +20 B 🔺
CDN Bundle - uncompressed 85.02 kB +0.05% +42 B 🔺
CDN Bundle (incl. Tracing) - uncompressed 140.58 kB +0.03% +42 B 🔺
CDN Bundle (incl. Logs, Metrics) - uncompressed 89.21 kB +0.05% +42 B 🔺
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 144.04 kB +0.03% +42 B 🔺
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 214.04 kB +0.02% +42 B 🔺
CDN Bundle (incl. Tracing, Replay) - uncompressed 259.29 kB +0.02% +42 B 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 262.73 kB +0.02% +42 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 272.99 kB +0.02% +42 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 276.42 kB +0.02% +42 B 🔺
@sentry/nextjs (client) 49.03 kB +0.05% +22 B 🔺
@sentry/sveltekit (client) 44.75 kB +0.06% +25 B 🔺
@sentry/node-core 60.56 kB +0.02% +9 B 🔺
@sentry/node 165.62 kB +0.01% +10 B 🔺
@sentry/node - without tracing 73.58 kB +0.02% +9 B 🔺
@sentry/aws-serverless 107.74 kB +0.01% +7 B 🔺
@sentry/cloudflare (withSentry) - minified 169.66 kB - -
@sentry/cloudflare (withSentry) 428.38 kB - -

View base workflow run

@chargome chargome marked this pull request as ready for review May 11, 2026 13:14
@chargome chargome requested a review from a team as a code owner May 11, 2026 13:14
Comment thread packages/browser/src/helpers.ts
Comment on lines +136 to +141
// When processEvent runs inside a sentryWrapped call, the outermost frame is always
// the sentryWrapped function. This works regardless of minification/bundling because
// it's a runtime check, not a source pattern match.
if (insideSentryWrapped) {
return true;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: In non-minified builds, isSentryInternalFrame incorrectly flags user code as internal when _sentryWrappedDepth > 0, causing valid events from wrapped functions to be silently dropped.
Severity: HIGH

Suggested Fix

Remove the unconditional check in isSentryInternalFrame that treats the frame at index 0 as internal when insideSentryWrapped is true. The logic relies on the assumption that the sentryWrapped frame is always present, but it is stripped out in non-minified builds before this filter runs. The check should be removed to prevent misclassifying user code as internal.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: packages/core/src/integrations/third-party-errors-filter.ts#L136-L141

Potential issue: In non-minified builds, the `isSentryInternalFrame` function
incorrectly assumes the first stack frame is always `sentryWrapped` when an error occurs
inside a wrapped function. However, a preceding function, `stripSentryFramesAndReverse`,
removes the `sentryWrapped` frame by its literal name. This causes the actual user code
frame to be misclassified as an internal Sentry frame and subsequently filtered out.
When all frames are filtered out, an `every()` check on the empty frame list becomes
vacuously true, causing the entire event to be silently dropped, even though it
originates from first-party code.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 1ae6a53. Configure here.

// it's a runtime check, not a source pattern match.
if (insideSentryWrapped) {
return true;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chained errors cause wrong frame filtered as internal

Medium Severity

When insideSentryWrapped is true, isSentryInternalFrame unconditionally returns true for frameIndex === 0. However, getFramesFromEvent concatenates frames from all exception.values entries in order — for chained errors (with cause), values[0] is the root cause, so index 0 in the combined array is the outermost frame of the root cause, not the sentryWrapped frame. This causes a legitimate user/library frame to be incorrectly filtered as Sentry-internal, potentially leading to false error drops or incorrect third-party tagging.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1ae6a53. Configure here.

// it's a runtime check, not a source pattern match.
if (insideSentryWrapped) {
return true;
}
Copy link
Copy Markdown
Member

@logaretm logaretm May 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this might be a legit issue, maybe we can narrow it down with something like:

const maybeInsideSentryWrapped = insideSentryWrapped && event.exception?.values?.length === 1;

and then gate it further to only the minified-shaped case:

function isLikelyMinifiedSentryWrappedFrame(frame: StackFrame): boolean {
  return !frame.context_line && !frame.pre_context && !!frame.function && frame.function.length <= 2;
}

WDYT?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ignoreSentryInternalFrames in thirdPartyErrorFilterIntegration doesn't work when minification enabled

2 participants