fix(browser): Add a synthetic stack trace to DOMException with empty stack traces if attachStacktrace is true#19988
Conversation
Semver Impact of This PR🟢 Patch (bug fixes) 📋 Changelog PreviewThis is how your changes will appear in the changelog. Bug Fixes 🐛
Internal Changes 🔧
🤖 This preview updates automatically when you update the PR. |
f16b753 to
0f76c44
Compare
…stack traces if attachStacktrace is true
8cb32a4 to
c26f7a3
Compare
|
LGTM, thanks! Let's see what the CI robots say :) |
|
Thank you for triggering the CI! The current failures appear to be unrelated to the changes in this PR. |
30ba39c to
83ae1e5
Compare
There was a problem hiding this comment.
Thanks for the PR!
I think this is a good change in general but if the test fails then we should ensure the exception report doesn't change. Let's see.
EDIT: Yep it fails, so I think the change will affect grouping significantly.
// before
"type": "SyntaxError",
"value": "The string did not match the expected pattern.",
// after
"type": "Error",
"value": "SyntaxError: The string did not match the expected pattern.",
| const domException = exception as DOMException; | ||
|
|
||
| if ('stack' in (exception as Error)) { | ||
| if ((exception as Error).stack) { |
There was a problem hiding this comment.
h: I think this will change how the dom exceptions are classified, I pushed a test to see if it would pass.
There was a problem hiding this comment.
Maybe something like this would keep the best of both worlds here, could you try something like:
// same check as before
if ('stack' in (exception as Error)) {
event = eventFromError(stackParser, exception as Error);
// preserves the classification while adding stacktraces if it exists...
const firstException = event.exception?.values?.[0];
if (attachStacktrace && syntheticException && firstException && !firstException.stacktrace) {
const frames = parseStackFrames(stackParser, syntheticException);
if (frames.length) {
firstException.stacktrace = { frames };
addExceptionMechanism(event, { synthetic: true });
}
}
} else {
// existing fallback
}| value: 'The string did not match the expected pattern.', | ||
| }, | ||
| ]); | ||
| }); |
There was a problem hiding this comment.
Contradictory test expects wrong branch behavior
Medium Severity
The test "preserves DOMException type when stack is an empty string" expects type: 'SyntaxError' and value: 'The string did not match the expected pattern.', but it has the same setup as the test at line 172 (stack = '', attachStacktrace = true), which expects type: 'Error' and value: 'SyntaxError: The string did not match the expected pattern.'. Tracing through the production code, the empty stack takes the eventFromString path, producing type: 'Error' and the combined name: message value. This test's expectations reflect the old eventFromError path behavior and will fail.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 83ae1e5. Configure here.
There was a problem hiding this comment.
This works against today's implementation, I'm just ensuring we lock it in and see if this PR changes it.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 901e3ef. Configure here.
| const domException = exception as DOMException; | ||
|
|
||
| if ('stack' in (exception as Error)) { | ||
| if ((exception as Error).stack) { |
There was a problem hiding this comment.
DOMException type classification lost for empty stack traces
Medium Severity
Changing the check from 'stack' in (exception as Error) to a truthy check causes DOMExceptions with empty stack strings to fall into the else branch, which uses eventFromString + addExceptionTypeValue. This loses the specific DOMException type (e.g., 'SyntaxError', 'NotAllowedError') and replaces it with a generic 'Error' type, because addExceptionTypeValue defaults the type to 'Error'. The exception value also changes from just the message to a name: message format. This regression in error classification will affect how users group and identify DOMException errors in Sentry. The contradictory test at line 190 (expecting type: 'SyntaxError') confirms this is a recognized problem — it will fail because the code actually produces type: 'Error'.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 901e3ef. Configure here.


DOMException may not always contain a stack trace. Depending on the browser, the stack property might be missing entirely, or it might be set to an empty string.
This PR ensures that empty strings are handled in the same way as missing properties.
For example, when a NotAllowedError occurs during WebAuthn usage, I confirmed that Chrome does not have the stack property, whereas Safari provides it as an empty string.