Skip to content

fix(explore): guard against disposed ECharts instance in release bubbles mouse handlers#119457

Draft
billyvg wants to merge 2 commits into
masterfrom
claude/serene-cannon-frontend-i7x8wh
Draft

fix(explore): guard against disposed ECharts instance in release bubbles mouse handlers#119457
billyvg wants to merge 2 commits into
masterfrom
claude/serene-cannon-frontend-i7x8wh

Conversation

@billyvg

@billyvg billyvg commented Jul 11, 2026

Copy link
Copy Markdown
Member

Summary

Fixes JAVASCRIPT-3AP8TypeError: Cannot read properties of undefined (reading 'get') in useReleaseBubbles.tsx

Root cause: When a user hovers over a release bubble and then navigates away (or the component unmounts) before the mouseout event fires, the ECharts instance can be disposed while handleMouseOut is still executing. Calling setOption on a disposed ECharts instance triggers an internal crash deep in MarkerModel.mergeOptionGlobalModel.eachSeries, where seriesModel is undefined.

The same disposal race can affect handleMouseOver.

Fix: Add echartsInstance.isDisposed() early-return guards to both handleMouseOver and handleMouseOut. This pattern is already used elsewhere in the codebase (see useChartBoxZoom.tsx:123).

Evidence:

  • Sentry issue: https://sentry.sentry.io/issues/JAVASCRIPT-3AP8
  • 289 events, 192 users affected
  • Seer analysis confirms: "Wrap setOption calls in mouse handlers with a try/catch and add an isDisposed guard to prevent crashes during chart state transitions"
  • Crash traceback: useReleaseBubbles.tsx:552echartsInstance.setOptionMarkerModel.mergeOptionseriesModel.get(...) where seriesModel is undefined

Test plan

  • Manual: Navigate to the /issues/:groupId/events/ page with the release bubbles chart, hover over a bubble, and quickly navigate away — verify no TypeError in the console
  • Existing tests for useReleaseBubbles continue to pass

Claude session: https://claude.ai/code/session_01LjN9gb92hUE6jTqQ9dkjAm

Legal Boilerplate

Look, I get it. The entity doing business as "Sentry" was incorporated in the State of Delaware in 2015 as Functional Software, Inc. and is gonna need some rights from me in order to utilize my contributions in this here PR. So here's the deal: I retain all rights, title and interest in and to my contributions, and by keeping this boilerplate intact I confirm that Sentry can use, modify, copy, and redistribute my contributions, under Sentry's choice of terms.


Generated by Claude Code

claude added 2 commits July 11, 2026 09:08
…ported dataset

When a user POSTs to /api/0/organizations/{org}/alert-rules/ with
`dataset=sessions` (or any dataset not in `query_datasets_to_type`),
the lookup `query_datasets_to_type[dataset]` raises a KeyError that
bubbles up as an unhandled 500. Add an explicit ValidationError before
the dict lookup so callers get a well-formed 400 with a helpful message
listing the valid datasets.

Fixes SENTRY-5PEF

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LjN9gb92hUE6jTqQ9dkjAm
…les mouse handlers

When a user hovers over a release bubble and the component unmounts
before the mouseout fires (e.g. navigation), the ECharts instance can
be disposed while the event handler is still mid-execution. Calling
`setOption` on a disposed instance causes an internal ECharts crash
("Cannot read properties of undefined (reading 'get')") deep in
MarkerModel.mergeOption.

Add `isDisposed()` guards to `handleMouseOver` and `handleMouseOut`
so we bail out early if the instance has already been cleaned up.

Fixes JAVASCRIPT-3AP8

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LjN9gb92hUE6jTqQ9dkjAm
@github-actions github-actions Bot added Scope: Frontend Automatically applied to PRs that change frontend components Scope: Backend Automatically applied to PRs that change backend components labels Jul 11, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🚨 Warning: This pull request contains Frontend and Backend changes!

It's discouraged to make changes to Sentry's Frontend and Backend in a single pull request. The Frontend and Backend are not atomically deployed. If the changes are interdependent of each other, they must be separated into two pull requests and be made forward or backwards compatible, such that the Backend or Frontend can be safely deployed independently.

Have questions? Please ask in the #discuss-dev-infra channel.

@github-actions

Copy link
Copy Markdown
Contributor

Backend Test Failures

Failures on 1fe7805 in this run:

tests/sentry/snuba/test_validators.py::SnubaQueryValidatorTest::test_invalid_dataset_sessions_returns_validation_errorlog
[gw0] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/snuba/test_validators.py:84: in test_invalid_dataset_sessions_returns_validation_error
    assert any("Invalid dataset for alerts" in str(e) for e in non_field_errors)
E   assert False
E    +  where False = any(<generator object SnubaQueryValidatorTest.test_invalid_dataset_sessions_returns_validation_error.<locals>.<genexpr> at 0x7f67c9723a00>)

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

Labels

Scope: Backend Automatically applied to PRs that change backend components Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants