Repository navigation
[BUG] Delegated mouseover listener crashes on synthetic events targeting document (dataset is undefined) #1277
Description
Bug description
In v6's event-delegation model, the single document-level mouseover listener throws TypeError: Cannot read properties of undefined (reading 'tooltipId') when an event's target is the document itself (not an Element).
This happens with synthetic / untrusted mouseover events, which are commonly dispatched directly on document by browser extensions, password managers, and accessibility/automation tooling. Real user hovers always target an Element, so this stays hidden in normal use but surfaces in production.
The crash is in resolveDataTooltipAnchor (src/utils/resolve-data-tooltip-anchor.ts):
function resolveDataTooltipAnchor(targetElement, tooltipId) {
let currentElement = targetElement; // = document
while (currentElement) {
if (currentElement.dataset.tooltipId === tooltipId) { // document.dataset is undefined -> throws
return currentElement;
}
currentElement = currentElement.parentElement;
}
return null;
}document.dataset is undefined (only HTMLElement / SVGElement expose dataset), so reading .tooltipId from it throws.
The guard in resolveAnchorElementRef (src/components/Tooltip/use-tooltip-events.tsx) only checks targetElement?.isConnected, but document.isConnected === true, so document slips through into the data-tooltip-id branch. Note the anchorSelector branch is wrapped in a try/catch, but the dataTooltipId branch is not, so the common data-tooltip-id usage is unprotected.
Package version
6.0.5 (also confirmed in 6.0.0)
To reproduce
- Render a tooltip using the default attribute anchor:
<a data-tooltip-id="my-tip">hover me</a> <Tooltip id="my-tip" content="hi" />
- Dispatch a synthetic mouseover on the document (this is what extensions/tooling do):
document.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
- The delegated listener runs
resolveDataTooltipAnchor(document, 'my-tip'), which doesdocument.dataset.tooltipIdand throws.
Expected behavior
The delegated mouseover/mouseout/etc. listeners should ignore non-Element targets (such as document) and not throw.
Actual behavior
Uncaught TypeError: Cannot read properties of undefined (reading 'tooltipId')
at resolveDataTooltipAnchor (resolve-data-tooltip-anchor.ts)
at resolveAnchorElementRef.current (use-tooltip-events.tsx)
at handler (use-tooltip-events.tsx)
at dispatch (event-delegation.ts)
The error escapes to window.onerror.
Suggested fix
Bail on non-Element targets at the guard, and/or harden the walk:
// use-tooltip-events.tsx - resolveAnchorElementRef.current
if (!(targetElement instanceof Element) || !targetElement.isConnected) {
return null;
}
// and/or resolve-data-tooltip-anchor.ts
while (currentElement) {
if (currentElement instanceof HTMLElement && currentElement.dataset.tooltipId === tooltipId) {
return currentElement;
}
currentElement = currentElement.parentElement;
}Environment
- OS: Windows 10+
- Browser: Chrome 139
- React version: 19
- Framework: Next.js
- Rendering mode: client
Additional context
Caught via production error monitoring (Sentry): 26 occurrences across 26 unique users over 3 days. The event payload confirms isTrusted: false and target: [object HTMLDocument] on the mouseover event, consistent with a synthetic event dispatched on document rather than a real user hover.
Activity
danielbarion commentedon Jun 1, 2026
@aramarakelyan88 can you please check the following beta release and let me know?
Beta version released with the last commit 🚀
or
aramarakelyan88 commentedon Jun 2, 2026
@danielbarion Verified —
6.0.5-beta.1278.rc.0fixes it. 🎉Tested the published artifact in Chrome (React 19) against the repro from the issue description:
mouseover/mouseoutdispatched ondocumentthrowsUncaught TypeError: Cannot read properties of undefined (reading 'tooltipId')events dispatched while the tooltip is open also don't throw
Thanks for the quick turnaround! Looking forward to the stable release.