Skip to content

TurboModuleContext: empty turbo_module.name/turbo_module.method tags cause a "Processing Error" (Discarded invalid value) on every event captured outside a TurboModule call #6502

Description

@abdouDiouf

OS

  • iOS (also applies to Android by code inspection)

SDK

@sentry/react-native 8.19.0 (bug present since 8.14.0, when the TurboModuleContext integration was introduced; still present in 8.19.0)

React Native version

0.81.5 (Expo SDK 54, New Architecture, Hermes)

Steps to reproduce

  1. Sentry.init({ dsn }) with default integrations (the TurboModuleContext integration is enabled by default).
  2. Capture any event while no TurboModule call is active — e.g. Sentry.captureMessage('test') from a Pressable's onPress.
  3. Open the event in Sentry.

Expected result

Event ingests cleanly. turbo_module.name / turbo_module.method tags are either absent (no active call) or carry the active call's values.

Actual result

Every such event is flagged with Event Processing Errors:

Discarded invalid value — tags.84.1 — expected a non-empty value
Discarded invalid value — tags.85.1 — expected a non-empty value

and the two tags show as <invalid> in the event's Tags section. Since most captures happen outside an active TurboModule call, effectively every JS-captured event carries the Processing Error badge, which is noisy and makes real ingestion problems hard to spot. (contexts.turbo_module is correctly cleared to null; only the tags are affected.)

Root cause

src/js/turbomodule/turboModuleTracker.tsclearScope deliberately writes an empty-string sentinel into both tags because the native setTag bridge only accepts strings:

// Empty-string sentinel for the "no active call" state. We don't pass
// `undefined` because the native `setTag(key, value)` TurboModule spec
// requires a string ...
const NO_ACTIVE_CALL = '';
function clearScope(scope) {
    scope.setContext(CONTEXT_KEY, null);
    scope.setTag(TAG_NAME, NO_ACTIVE_CALL);
    scope.setTag(TAG_METHOD, NO_ACTIVE_CALL);
}

But Sentry ingestion rejects empty tag values, so the sentinel is discarded at ingestion with a visible processing error on the event.

Suggested fix

We patched this locally (patch-package on 8.19.0) by stripping the sentinel tags in the integration's existing processEvent, which keeps the feature intact (context always preserved; tags preserved whenever they hold real values):

// in turboModuleContextIntegration's processEvent(event):
if (event.tags) {
    if (event.tags['turbo_module.name'] === '') {
        delete event.tags['turbo_module.name'];
    }
    if (event.tags['turbo_module.method'] === '') {
        delete event.tags['turbo_module.method'];
    }
}

Verified on device: with this change the Processing Error disappears and contexts.turbo_module / real tag values are unaffected.

Known limitation of the JS-side fix: native fatal-crash events are assembled by the native SDKs and skip JS processEvent, so a crash occurring outside any TurboModule call can still carry the empty tags. A complete fix probably needs the native scopes to support removing a tag (or the native SDKs to drop empty tag values before sending).

Are you willing to submit a PR?

Happy to turn the processEvent change above into a PR if the approach is acceptable.

Metadata

Metadata

Assignees

Labels

BugImprovementReact-Nativeup-for-grabs✋ We would really appreciate anyone interested in working on this to submit a PR!

Projects

Status
No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions