Skip to content

eventLoopBlockIntegration: breadcrumbs are dropped from EventLoopBlocked events (Scope.update() ignores the breadcrumbs field) #22314

Description

@beyondkmp

Summary

Breadcrumbs are silently dropped from EventLoopBlocked events sent by eventLoopBlockIntegration (from @sentry/node-native) because Scope.update() does not copy the breadcrumbs field from a plain scope-data object.

Reproduction

const Sentry = require('@sentry/node');
const { eventLoopBlockIntegration } = require('@sentry/node-native');

Sentry.init({
  dsn: '__YOUR_DSN__',
  integrations: [eventLoopBlockIntegration({ threshold: 1000 })],
});

Sentry.addBreadcrumb({ category: 'test', message: 'breadcrumb before block', level: 'info' });

// 1. Sanity check: a normal event DOES include the breadcrumb
Sentry.captureException(new Error('normal event'));

// 2. Block the event loop past the threshold to trigger an EventLoopBlocked event
setTimeout(() => {
  const end = Date.now() + 3000;
  while (Date.now() < end) { /* busy loop */ }
}, 2000);

Root cause

In the watchdog worker (packages/node-native/src/event-loop-block-watchdog.ts), the scope is reconstructed like this:

const scope = crashedThread.pollState?.scope
  ? new Scope().update(crashedThread.pollState.scope).getScopeData()
  : new Scope().getScopeData();
applyScopeToEvent(event, scope);

Scope.update() in @sentry/core only copies tags, attributes, extra, user, contexts, level, fingerprint, propagationContext, and conversationId — it never reads breadcrumbs or attachments. The fresh Scope retains its empty _breadcrumbs, so applyScopeToEvent overwrites the event's breadcrumbs with undefined.

The same round-trip also drops attachments.

Suggested fix

The safest targeted fix is to carry breadcrumbs (and attachments) over explicitly after reconstructing the scope in event-loop-block-watchdog.ts, similar to what the old anrIntegration worker did:

const scope = crashedThread.pollState?.scope
  ? new Scope().update(crashedThread.pollState.scope).getScopeData()
  : new Scope().getScopeData();
scope.breadcrumbs = crashedThread.pollState?.scope?.breadcrumbs ?? [];

Environment

  • @sentry/electron: 7.15.0
  • @sentry/node-native: 10.62.0
  • @sentry/core: 10.62.0
  • Electron: 40

Metadata

Metadata

Assignees

Projects

Status
Waiting for: Product Owner

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions