Skip to content

fix(releaseBubbles): guard echarts mouse handlers against disposed instance#119460

Draft
billyvg wants to merge 1 commit into
masterfrom
claude/serene-cannon-0quk6a
Draft

fix(releaseBubbles): guard echarts mouse handlers against disposed instance#119460
billyvg wants to merge 1 commit into
masterfrom
claude/serene-cannon-0quk6a

Conversation

@billyvg

@billyvg billyvg commented Jul 11, 2026

Copy link
Copy Markdown
Member

Summary

Fixes a TypeError: Cannot read properties of undefined (reading 'get') crash in useReleaseBubbles.tsx that is escalating in production (Sentry issue JAVASCRIPT-3AP8, 290 events, 193 users affected).

Root cause

All five echarts event handlers in handleChartRef (handleMouseMove, handleMouseOver, handleMouseOut, handleGlobalOut, handleLegendSelectChanged) checked !echartsInstance but did not check echartsInstance.isDisposed().

The crash path is:

  1. User moves mouse over the release bubbles chart
  2. zrender's native mousemove DOM handler fires and internally dispatches a mouseout event via Handler.prototype.dispatchToElement
  3. This reaches our registered handleMouseOut callback
  4. handleMouseOut calls echartsInstance.setOption(...) — but at this point the chart is mid-teardown (deps changed, triggering cleanup + re-registration, or component is unmounting)
  5. ECharts' GlobalModel._mergeOption iterates _seriesIndices and hits a stale/undefined seriesModel, throwing TypeError: Cannot read properties of undefined (reading 'get')

Fix

Add echartsInstance.isDisposed() to the guard condition in all five handlers. ECharts sets this flag synchronously when dispose() is called, so the check is reliable.

if (!echartsInstance || echartsInstance.isDisposed()) return;

This is the approach recommended by Seer analysis on the issue.

Evidence

  • Sentry issue: https://sentry.sentry.io/issues/JAVASCRIPT-3AP8
  • 290 occurrences, 193 users, escalating since 2026-07-06
  • Stack trace confirms crash at useReleaseBubbles.tsx:552 inside handleMouseOut → setOption → GlobalModel._mergeOption → eachSeries → seriesModel.get
  • Seer actionability: medium

Claude session

https://claude.ai/code/session_01RgKuwi8ia6932f3JRJau9x


Generated by Claude Code

Adds isDisposed() checks to all mouse/legend event handlers in
useReleaseBubbles so that they bail out if the echarts instance has
been disposed before the event fires. Fixes the crash where
echartsInstance.setOption() is called during a chart state transition
(e.g. dep-driven re-render) after the model has been torn down,
causing MarkerModel._mergeOption to iterate a stale _seriesIndices
array and hit undefined seriesModel.

Fixes JAVASCRIPT-3AP8

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RgKuwi8ia6932f3JRJau9x
@github-actions github-actions Bot added the Scope: Frontend Automatically applied to PRs that change frontend components label Jul 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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