Skip to content

🐛 Handle non-Error debugger throw values#4740

Open
watson wants to merge 1 commit into
watson/cleanup-testsfrom
watson/support-non-error-thrown
Open

🐛 Handle non-Error debugger throw values#4740
watson wants to merge 1 commit into
watson/cleanup-testsfrom
watson/support-non-error-thrown

Conversation

@watson
Copy link
Copy Markdown
Collaborator

@watson watson commented Jun 7, 2026

Motivation

JavaScript can throw any value, not just Error instances. The debugger onThrow hook treated caught values as Error, which meant a thrown string produced an undefined throwable message and assumed a stacktrace was available.

Changes

onThrow now accepts the thrown value as unknown, stores it as such in the active entry, and normalizes the throwable payload at snapshot creation time.

Error values keep their message and parsed stacktrace. Non-Error values are formatted safely and send an empty stacktrace to preserve the current Live Debugger UI contract.

Debugger throwable formatting now uses the shared browser-core isError() helper so cross-realm Errors, such as iframe-created Errors, keep their throwable details. The shared helper is also guarded so hostile Symbol.toStringTag getters cannot throw from error detection.

Unit tests cover thrown strings, cross-realm Errors, and values that cannot be coerced to strings.

Test instructions

Run yarn test:unit --spec packages/browser-debugger/src/domain/api.spec.ts.

Run yarn test:unit --spec packages/browser-core/src/domain/error/error.spec.ts.

Checklist

  • Tested locally
  • Tested on staging
  • Added unit tests for this change.
  • Added e2e/integration tests for this change.
  • Updated documentation and/or relevant AGENTS.md file

@watson watson requested review from a team as code owners June 7, 2026 05:15
Copy link
Copy Markdown
Collaborator Author

watson commented Jun 7, 2026

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

@cit-pr-commenter-54b7da
Copy link
Copy Markdown

cit-pr-commenter-54b7da Bot commented Jun 7, 2026

Bundles Sizes Evolution

📦 Bundle Name Base Size Local Size 𝚫 𝚫% Status
Rum 171.86 KiB 171.88 KiB +20 B +0.01%
Rum Profiler 7.88 KiB 7.88 KiB 0 B 0.00%
Rum Recorder 21.21 KiB 21.21 KiB 0 B 0.00%
Logs 54.31 KiB 54.33 KiB +20 B +0.04%
Rum Slim 129.69 KiB 129.71 KiB +20 B +0.02%
Worker 22.96 KiB 22.96 KiB 0 B 0.00%

@datadog-prod-us1-5
Copy link
Copy Markdown

datadog-prod-us1-5 Bot commented Jun 7, 2026

Pipelines  Tests

Fix all issues with BitsAI

⚠️ Warnings

🚦 1 Pipeline job failed

DataDog/browser-sdk | format   View in Datadog   GitLab

ℹ️ Info

No other issues found (see more)

🧪 All tests passed
❄️ No new flaky tests detected

🎯 Code Coverage (details)
Patch Coverage: 71.43%
Overall Coverage: 76.77% (+0.00%)

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: f32c7a4 | Docs | Datadog PR Page | Give us feedback!

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 03b6d4c0c6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/browser-debugger/src/domain/api.ts Outdated
Comment thread packages/browser-debugger/src/domain/api.ts Outdated
@watson watson changed the base branch from main to graphite-base/4740 June 7, 2026 05:21
@watson watson force-pushed the watson/support-non-error-thrown branch from 03b6d4c to 9c9b8ac Compare June 7, 2026 05:21
@watson watson changed the base branch from graphite-base/4740 to watson/cleanup-tests June 7, 2026 05:21
JavaScript allows throwing arbitrary values, but the debugger hook typed thrown
values as Error and read message/stack unconditionally.

Type thrown values as unknown, safely format non-Error throwables, and keep an
empty stacktrace for the current Live Debugger UI contract.

Reuse the shared browser-core isError helper for cross-realm Error detection and
make it non-throwing for hostile toStringTag getters.

Add unit tests covering thrown strings, cross-realm Errors, and values that
cannot be coerced to strings.
@watson watson force-pushed the watson/support-non-error-thrown branch from 9c9b8ac to f32c7a4 Compare June 7, 2026 05:43
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f32c7a4f83

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

try {
return String(error)
} catch {
return jsonStringify(sanitize(error)) ?? '<error: unable to stringify thrown value>'
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Guard the sanitizer fallback for hostile thrown values

issue: For a non-Error thrown object whose primitive coercion fails and whose enumerable getter also throws (for example { toString() { throw ... }, get x() { throw ... } }), this fallback still lets sanitize(error) throw while $dd_throw is running inside the instrumented catch before the original throw e pattern (test/apps/instrumentation-overhead/src/instrumented.ts). The fresh evidence after the prior review is this new sanitizer fallback path: it catches String(error) but not failures from sanitizing the same thrown value, so the SDK can still replace the application's original exception instead of only recording a snapshot.

Useful? React with 👍 / 👎.

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.

1 participant