Skip to content

fix(core): Attach debug_meta to Hermes JS error events via Debug ID lookup - #6545

Merged
lucas-zimerman merged 5 commits into
mainfrom
fix/6480-debug-meta-hermes
Aug 5, 2026
Merged

fix(core): Attach debug_meta to Hermes JS error events via Debug ID lookup#6545
lucas-zimerman merged 5 commits into
mainfrom
fix/6480-debug-meta-hermes

Conversation

@antonis

@antonis antonis commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

📢 Type of change

  • Bugfix

📜 Description

On React Native + Hermes (including Expo OTA / expo export Hermes bundles), plain JS exception events often ship without debug_meta.images, even when Metro injected the Debug ID premodule (_sentryDebugIds) and the matching artifact bundle was uploaded with that Debug ID.

The core prepareEvent pipeline attempts this via applyDebugIdsapplyDebugMeta, but that path re-parses the premodule Error().stack and requires an exact filename match against the exception frames. That match is fragile for Hermes premodule stacks, so filenameDebugIdMap ends up empty and no debug_meta is attached.

Profiling already solves the same problem robustly via getDebugMetadata() (profiling/debugid.ts): it reads _sentryDebugIds directly and stamps a single sourcemap image with the canonical bundle code_file (app:///index.android.bundle / app:///main.jsbundle) — no stack reparse. That helper was not wired into the error event pipeline.

This PR adds a default debugMetaIntegration that reuses getDebugMetadata() to stamp debug_meta.images on error events. Key details:

  • Scoped to error events (event.type === undefined) — transactions, profiles and other event types are untouched.
  • Idempotent against core. Core runs applyDebugIds (sets frame.debug_id) before event processors and applyDebugMeta (stamps images) after them. The integration detects a successful core match via frame.debug_id and backs off, so core's own stamp is not duplicated. When core fails to match (the bug case), the integration fills the gap.
  • Defensive dedupe by debug_id, and preserves unrelated pre-existing images (e.g. native images added by nativeLinkedErrors).
  • Registered right after createReactNativeRewriteFrames() so the canonical bundle filename is already in place.

💡 Motivation and Context

Without debug_meta, backends fall back to release + filename matching. RN/Expo rewrites every JS frame to the same canonical filename, and OTA updates keep the native release, so the native build's Hermes map can be applied to OTA bytecode → wrong files/lines. The missing debug_meta is an SDK-side gap regardless of backend.

Fixes #6480

💚 How did you test it?

  • Added test/integrations/debugmeta.test.ts covering: stamping on error events, no-op when no Debug ID, skipping non-error events, backing off when core matched, and preserving pre-existing images.
  • Added tests that reproduce the core prepareEvent ordering (applyDebugIds → event processor → applyDebugMeta) and assert exactly one image results whether core succeeds or fails — guarding against a duplicate-image regression.
  • Regenerated the API report for the new public debugMetaIntegration.

📝 Checklist

  • I added tests to verify changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • All tests passing.
  • Public API changes reviewed by another Mobile SDK team member or implemented according to the develop docs spec.
  • No breaking changes.

🔮 Next steps

  • Confirm naming (debugMetaIntegration) — the mechanism is RN/Hermes-specific (single bundle per platform); a more specific name could be used if preferred.

🤖 Generated with Claude Code

…ookup

Error events relied on the core applyDebugIds path, which re-parses the
Metro-injected premodule Error().stack and requires an exact filename
match against the exception frames. That match is fragile for Hermes
premodule stacks, so events frequently shipped without debug_meta and
symbolication fell back to release + filename matching (broken for
Expo OTA updates that keep the native release).

Add a debugMetaIntegration that reuses profiling's direct Debug ID
lookup (getDebugMetadata) to stamp debug_meta.images for error events.
It backs off when core already matched the stack (frame.debug_id set)
to avoid emitting a duplicate image, and dedupes defensively.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Semver Impact of This PR

None (no version bump detected)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


  • fix(core): Attach debug_meta to Hermes JS error events via Debug ID lookup by antonis in #6545
  • release: 8.23.0 by alwx in 580759e8
  • fix(core): Use the debug logger, not the Logs API, for SDK diagnostics by alwx in #6585
  • chore(deps): update Wizard to v7.0.2 by github-actions in #6569
  • chore(deps): update Sentry Android Gradle Plugin to v6.18.0 by github-actions in #6571
  • fix(core): Measure callback-style native module calls until completion by alwx in #6561
  • chore(deps): bump brace-expansion to ^2.1.4 / ^5.0.9 by alwx in #6577
  • fix(expo): Resolve config-plugins through the expo package by alwx in #6581
  • chore(deps): bump js-yaml to ^3.15.1 / ^4.3.1 by alwx in #6578
  • docs(core): Correct enableTurboModuleTracking docs and document TurboModule plumbing by alwx in #6582
  • docs: fix dead links in the README by luccasfraga in #6570
  • chore(deps): update Maestro to v2.8.0 by github-actions in #6551
  • chore(deps): update Android SDK to v8.52.0 by github-actions in #6566
  • chore(deps): bump the codeql-action group with 3 updates by dependabot in #6572
  • chore(deps): bump getsentry/craft/.github/workflows/changelog-preview.yml from 2.28.0 to 2.30.0 by dependabot in #6573
  • chore(deps): bump getsentry/craft from 2.28.0 to 2.30.0 by dependabot in #6575
  • chore(deps): bump dorny/paths-filter from 4.0.2 to 4.0.3 by dependabot in #6574
  • chore(deps): bump nanoid from 3.3.8 to 3.3.18 by dependabot in #6579
  • chore(deps): bump gradle/actions/setup-gradle from 6.2.0 to 6.3.0 by dependabot in #6576
  • chore(ci): remove Cirrus runners and use only Bitrise by itaybre in #6563
  • fix(ios): Re-land SentrySDK.internal migration, bump Cocoa SDK to 9.24.0 by alwx in #6541
  • ci: Replace curl-pipe-bash with action-setup-cli for Sentry CLI setup by oioki in #6567
  • release: 8.22.0 by alwx in e8ef9202
  • test(e2e): Add TurboModule sample coverage and e2e validation by alwx in #6549

Plus 17 more


🤖 This preview updates automatically when you update the PR.

@antonis
antonis force-pushed the fix/6480-debug-meta-hermes branch from 073c8a0 to f40d5e0 Compare July 30, 2026 15:51
@antonis antonis added the ready-to-merge Triggers the full CI test suite label Jul 30, 2026
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@antonis

antonis commented Jul 30, 2026

Copy link
Copy Markdown
Contributor Author

@sentry review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 3b10f42. Configure here.

@sentry

sentry Bot commented Jul 30, 2026

Copy link
Copy Markdown

📲 Install Builds

Android

🔗 App Name App ID Version Configuration
Sentry RN io.sentry.reactnative.sample 8.21.0 (101) Release

⚙️ sentry-react-native Build Distribution Settings

@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

iOS (legacy) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 3836.12 ms 1219.96 ms -2616.17 ms
Size 5.08 MiB 6.68 MiB 1.60 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
ecf47a2+dirty 3835.20 ms 1222.43 ms -2612.77 ms
3817909+dirty 1183.90 ms 1187.50 ms 3.60 ms
5ee78d6+dirty 3847.52 ms 1224.27 ms -2623.25 ms
890d145+dirty 1223.59 ms 1231.37 ms 7.78 ms
e763471+dirty 3841.16 ms 1218.06 ms -2623.09 ms
3d31fcf+dirty 3838.09 ms 1223.46 ms -2614.63 ms
9210ae6+dirty 3815.93 ms 1214.14 ms -2601.79 ms
26843eb+dirty 3861.60 ms 1238.77 ms -2622.82 ms
7a89652+dirty 3861.46 ms 1229.61 ms -2631.85 ms
9ad4522+dirty 3850.40 ms 1222.40 ms -2628.00 ms

App size

Revision Plain With Sentry Diff
ecf47a2+dirty 4.98 MiB 6.46 MiB 1.49 MiB
3817909+dirty 3.38 MiB 4.73 MiB 1.35 MiB
5ee78d6+dirty 5.15 MiB 6.69 MiB 1.53 MiB
890d145+dirty 3.38 MiB 4.77 MiB 1.38 MiB
e763471+dirty 4.98 MiB 6.51 MiB 1.53 MiB
3d31fcf+dirty 4.98 MiB 6.56 MiB 1.58 MiB
9210ae6+dirty 5.15 MiB 6.68 MiB 1.53 MiB
26843eb+dirty 4.98 MiB 6.53 MiB 1.55 MiB
7a89652+dirty 5.15 MiB 6.70 MiB 1.55 MiB
9ad4522+dirty 4.98 MiB 6.56 MiB 1.58 MiB

Previous results on branch: fix/6480-debug-meta-hermes

Startup times

Revision Plain With Sentry Diff
384cb83+dirty 3856.39 ms 1219.55 ms -2636.84 ms
088b29e+dirty 3867.30 ms 1221.30 ms -2646.00 ms

App size

Revision Plain With Sentry Diff
384cb83+dirty 4.98 MiB 6.56 MiB 1.58 MiB
088b29e+dirty 4.98 MiB 6.56 MiB 1.58 MiB

@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

iOS (new) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 3825.63 ms 1211.94 ms -2613.69 ms
Size 5.08 MiB 6.68 MiB 1.60 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
71abba0+dirty 3852.70 ms 1224.53 ms -2628.16 ms
bc0d8cf+dirty 3834.64 ms 1223.91 ms -2610.73 ms
68ae91b+dirty 3836.36 ms 1222.04 ms -2614.32 ms
267d3ed+dirty 3860.14 ms 1223.39 ms -2636.76 ms
f170ec3+dirty 3844.74 ms 1222.67 ms -2622.07 ms
b9bebee+dirty 3858.02 ms 1231.92 ms -2626.11 ms
d038a14+dirty 3831.11 ms 1216.30 ms -2614.81 ms
853723c+dirty 3849.33 ms 1221.07 ms -2628.26 ms
e763471+dirty 3826.10 ms 1221.52 ms -2604.58 ms
3d31fcf+dirty 3857.46 ms 1237.17 ms -2620.29 ms

App size

Revision Plain With Sentry Diff
71abba0+dirty 5.15 MiB 6.67 MiB 1.52 MiB
bc0d8cf+dirty 5.15 MiB 6.67 MiB 1.51 MiB
68ae91b+dirty 4.98 MiB 6.46 MiB 1.48 MiB
267d3ed+dirty 5.15 MiB 6.69 MiB 1.54 MiB
f170ec3+dirty 5.15 MiB 6.69 MiB 1.53 MiB
b9bebee+dirty 5.15 MiB 6.68 MiB 1.53 MiB
d038a14+dirty 5.15 MiB 6.67 MiB 1.51 MiB
853723c+dirty 5.15 MiB 6.69 MiB 1.53 MiB
e763471+dirty 4.98 MiB 6.51 MiB 1.53 MiB
3d31fcf+dirty 4.98 MiB 6.56 MiB 1.58 MiB

Previous results on branch: fix/6480-debug-meta-hermes

Startup times

Revision Plain With Sentry Diff
384cb83+dirty 3844.38 ms 1221.17 ms -2623.21 ms
088b29e+dirty 3851.37 ms 1214.07 ms -2637.30 ms

App size

Revision Plain With Sentry Diff
384cb83+dirty 4.98 MiB 6.56 MiB 1.58 MiB
088b29e+dirty 5.08 MiB 6.68 MiB 1.60 MiB

@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Android (legacy) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 416.88 ms 456.98 ms 40.10 ms
Size 49.74 MiB 55.44 MiB 5.70 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
27d9693+dirty 419.08 ms 469.12 ms 50.04 ms
04207c4+dirty 459.19 ms 518.54 ms 59.35 ms
8929511+dirty 405.33 ms 452.16 ms 46.83 ms
eb93136+dirty 416.18 ms 467.32 ms 51.14 ms
c004dae+dirty 412.86 ms 481.50 ms 68.64 ms
3b6e9f9+dirty 442.70 ms 486.44 ms 43.74 ms
0bd8916+dirty 412.77 ms 451.31 ms 38.54 ms
bc8f61e+dirty 442.98 ms 506.56 ms 63.58 ms
7d8c8bd+dirty 417.45 ms 462.10 ms 44.65 ms
a0d8cf8+dirty 411.71 ms 467.57 ms 55.87 ms

App size

Revision Plain With Sentry Diff
27d9693+dirty 49.74 MiB 55.09 MiB 5.34 MiB
04207c4+dirty 43.75 MiB 48.12 MiB 4.37 MiB
8929511+dirty 43.75 MiB 48.16 MiB 4.41 MiB
eb93136+dirty 48.30 MiB 53.58 MiB 5.28 MiB
c004dae+dirty 48.30 MiB 53.49 MiB 5.19 MiB
3b6e9f9+dirty 48.30 MiB 53.54 MiB 5.23 MiB
0bd8916+dirty 48.30 MiB 53.57 MiB 5.26 MiB
bc8f61e+dirty 49.74 MiB 55.09 MiB 5.35 MiB
7d8c8bd+dirty 48.30 MiB 53.54 MiB 5.23 MiB
a0d8cf8+dirty 48.30 MiB 53.49 MiB 5.19 MiB

Previous results on branch: fix/6480-debug-meta-hermes

Startup times

Revision Plain With Sentry Diff
384cb83+dirty 423.51 ms 487.04 ms 63.53 ms
088b29e+dirty 488.18 ms 529.24 ms 41.06 ms

App size

Revision Plain With Sentry Diff
384cb83+dirty 49.74 MiB 55.38 MiB 5.64 MiB
088b29e+dirty 49.74 MiB 55.44 MiB 5.70 MiB

@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Android (new) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 433.72 ms 489.82 ms 56.10 ms
Size 49.74 MiB 55.44 MiB 5.70 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
27d9693+dirty 438.63 ms 514.08 ms 75.46 ms
68672fc+dirty 407.55 ms 442.96 ms 35.41 ms
15d4514+dirty 413.63 ms 449.62 ms 35.99 ms
882f8ae+dirty 408.19 ms 435.86 ms 27.67 ms
bc8f61e+dirty 419.31 ms 453.39 ms 34.08 ms
21a1e70+dirty 437.55 ms 507.10 ms 69.56 ms
4acd4e9+dirty 431.33 ms 477.68 ms 46.35 ms
20fbd51+dirty 594.38 ms 655.35 ms 60.97 ms
5a316ea+dirty 626.41 ms 645.00 ms 18.59 ms
ecf47a2+dirty 457.21 ms 498.10 ms 40.89 ms

App size

Revision Plain With Sentry Diff
27d9693+dirty 49.74 MiB 55.09 MiB 5.34 MiB
68672fc+dirty 48.30 MiB 53.61 MiB 5.31 MiB
15d4514+dirty 48.30 MiB 53.60 MiB 5.30 MiB
882f8ae+dirty 48.30 MiB 53.60 MiB 5.29 MiB
bc8f61e+dirty 49.74 MiB 55.09 MiB 5.35 MiB
21a1e70+dirty 49.74 MiB 54.82 MiB 5.07 MiB
4acd4e9+dirty 49.74 MiB 55.26 MiB 5.52 MiB
20fbd51+dirty 49.74 MiB 54.81 MiB 5.07 MiB
5a316ea+dirty 49.74 MiB 55.09 MiB 5.34 MiB
ecf47a2+dirty 49.74 MiB 54.82 MiB 5.07 MiB

Previous results on branch: fix/6480-debug-meta-hermes

Startup times

Revision Plain With Sentry Diff
384cb83+dirty 425.08 ms 477.16 ms 52.08 ms
088b29e+dirty 444.83 ms 478.30 ms 33.47 ms

App size

Revision Plain With Sentry Diff
384cb83+dirty 49.74 MiB 55.38 MiB 5.64 MiB
088b29e+dirty 49.74 MiB 55.44 MiB 5.70 MiB

@antonis
antonis marked this pull request as ready for review July 31, 2026 05:28
@antonis
antonis requested review from a team, alwx and lucas-zimerman as code owners July 31, 2026 05:28
@antonis antonis removed the ready-to-merge Triggers the full CI test suite label Jul 31, 2026

@antonis antonis left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Also fixed the duplicate fixes section with 9b3f3a6

return event;
}

event.debug_meta = event.debug_meta || {};

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
event.debug_meta = event.debug_meta || {};
event.debug_meta ??= {};

@lucas-zimerman lucas-zimerman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM!

@lucas-zimerman lucas-zimerman added the ready-to-merge Triggers the full CI test suite label Aug 4, 2026
@lucas-zimerman
lucas-zimerman merged commit a9672d9 into main Aug 5, 2026
114 of 120 checks passed
@lucas-zimerman
lucas-zimerman deleted the fix/6480-debug-meta-hermes branch August 5, 2026 10:44
@github-actions

Copy link
Copy Markdown
Contributor
Fails
🚫 Please consider adding a changelog entry for the next release.

Instructions and example for changelog

Please add an entry to CHANGELOG.md to the "Unreleased" section. Make sure the entry includes this PR's number.

Example:

## Unreleased

### Fixes

- Attach debug_meta to Hermes JS error events via Debug ID lookup ([#6545](https://github.com/getsentry/sentry-react-native/pull/6545))

If none of the above apply, you can opt out of this check by adding #skip-changelog to the PR description or adding a skip-changelog label.

Generated by 🚫 dangerJS against 9b3f3a6

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

Labels

ready-to-merge Triggers the full CI test suite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

JS exceptions often lack debug_meta on Hermes; profiling path already has a robust Debug ID lookup

2 participants