microsoft / microsoft/fluentui
[Bug]: Legends OverflowMenu crashes after the legend count changes (`items[i]` is undefined)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 20.3k
- Forks
- 2.9k
- Avg merge
- 2d 9h
- Merged PRs (30d)
- 46
Description
Charting Control
Legends, observed through VerticalStackedBarChart.
Package version
@fluentui/react-charts 9.3.25. The affected code is also present in 9.3.24 and remains unchanged on master as of 2026-09-03.
React version
19.2.8
Environment
System:
OS: Windows 11 10.0.26200
CPU: (8) x64 11th Gen Intel(R) Core(TM) i5-1145G7 @ 2.60GHz
Browsers:
Chrome: 151.0.7922.174
Edge: Chromium (151.0.4129.107)
npmPackages:
react: 19.2.8
react-dom: 19.2.8
@fluentui/react-charts: 9.3.25
@types/react: 19.2.18
Current Behavior
A chart can crash when the number of rendered legends changes while some legends overflow. In our VerticalStackedBarChart case, opening the "+N more" menu and moving across its items triggers rerenders and eventually throws:
Uncaught TypeError: Cannot read properties of undefined (reading 'props')
The error propagates to the React error boundary and unmounts the view. Rapid chart-data changes can trigger the same failure without hover.
The immediate failure is in OverflowMenu.tsx:
const remainingItemsCount = itemIds.length - overflowCount;
for (let i = remainingItemsCount; i < itemIds.length; i++) {
const buttonElement = items[i];
const value = `${buttonElement.props['data-title'] ?? i}`;
itemIds and items are rebuilt synchronously from the current dataToRender, so they normally have equal lengths. The transient mismatch is with overflowCount: it comes from useOverflowMenu() and reflects the registered OverflowItem snapshot. When the legend set shrinks, that snapshot can still describe the previous render. If the previous overflowCount is greater than the current itemIds.length, remainingItemsCount is negative and items[i] is undefined.
Hover makes this especially visible in VerticalStackedBarChart when data points omit color. _getLegendData() chooses a random fallback color on every render and deduplicates by both title and color. Hover updates activeLegend, causing another render; the random title/color combinations can change the deduplicated legend count while the overflow registration snapshot still reflects the previous render. The unstable fallback-color behavior is already tracked separately in #31364, but OverflowMenu should remain safe for any legitimate dynamic legend-count change.
Expected Behavior
Changing or interacting with chart data must not crash the overflow menu. During a transient mismatch between the current legend array and the overflow snapshot, OverflowMenu should ignore out-of-range entries and reconcile on the next overflow update.
Reproduction
A deterministic regression test can extend the real v9 overflow harness already proposed in #36490:
- Mock a constrained container so 17 legends produce an overflow count (the PR's current setup yields 14).
- Render
Legendswith all 17 items. - Rerender the same component with only 3 items.
- Before the old overflow registrations reconcile,
OverflowMenucomputes3 - 14 = -11and readsitems[-11].props, reproducing the exception.
The application-level reproduction uses a VerticalStackedBarChart with 24 x-axis buckets and chart points that omit explicit colors:
- Render the chart in a container narrow enough to show the "+N more" legend menu.
- Open the menu.
- Move the pointer repeatedly across the menu items.
- Observe
TypeError: Cannot read properties of undefined (reading 'props').
Suggested fix
Defensively skip an index that does not exist in the current items array:
const buttonElement = items[i];
if (!buttonElement) {
continue;
}
We carry this guard locally in both the ESM and CommonJS builds, and it eliminates the crash in downstream browser testing. Clamping remainingItemsCount to zero would address the negative-index case, but the element guard is still valuable protection against any transient count mismatch.
A regression test should cover a dynamic shrink while items are overflowed. The static overflow tests in #36490 do not currently exercise that transition.
Are you reporting an Accessibility issue?
No.
Suggested severity
Medium - Has workaround.
Products/sites affected
Private enterprise operations application.
Are you willing to submit a PR to fix?
No.
Validations
- Checked for an existing issue reporting the same crash. Related issues #31364 and #32121 cover fallback colors and overflow test coverage, not this exception.
- The report includes a minimal deterministic regression case and the application-level trigger.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in packages/charts/react-charts/library/src/components/Legends/OverflowMenu.tsx and review the v9 overflow harness proposed in #36490. Reproduce a shrink from 17 overflowed legends to 3, then add regression coverage for the transient mismatch. Done means dynamic legend changes and overflow-menu interaction no longer throw when the current items are shorter than the overflow snapshot.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript
- Domain
- frontend, testing-qa
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100