plotly/plotly.js · warning
Unrecognized subplot: ${spId}
Error message
Unrecognized subplot: ${spId} What it means
Fx.hover resolves each requested subplot id (e.g. 'xy', 'x2y2', 'polar', 'geo') against fullLayout to find the axes to hover on. If the id is neither the default xy pair nor a known subplot with a _subplot object, it warns 'Unrecognized subplot: <id>' and aborts the hover.
Source
Thrown at src/components/fx/hover.js:342
var xaArray = new Array(len);
var yaArray = new Array(len);
var supportsCompare = false;
for (var i = 0; i < len; i++) {
spId = subplots[i];
if (plots[spId]) {
// 'cartesian' case
supportsCompare = true;
xaArray[i] = plots[spId].xaxis;
yaArray[i] = plots[spId].yaxis;
} else if (fullLayout[spId] && fullLayout[spId]._subplot) {
// other subplot types
var _subplot = fullLayout[spId]._subplot;
xaArray[i] = _subplot.xaxis;
yaArray[i] = _subplot.yaxis;
} else {
Lib.warn('Unrecognized subplot: ' + spId);
return;
}
}
if (hovermode && !supportsCompare) hovermode = 'closest';
if (
['x', 'y', 'closest', 'x unified', 'y unified'].indexOf(hovermode) === -1 ||
!gd.calcdata ||
gd.querySelector('.zoombox') ||
gd._dragging
) {
return dragElement.unhoverRaw(gd, evt);
}
var hoverdistance = fullLayout.hoverdistance;
if (hoverdistance === -1) hoverdistance = Infinity;
View on GitHub (pinned to 1d090e0b5f)
Solutions
- Verify the id exists: Plotly.d3.keys(gd._fullLayout) or check gd._fullLayout[spId] before calling Fx.hover.
- Derive subplot ids dynamically from the figure (gd._fullLayout._subplots) instead of hard-coding.
- Use the correct id format: cartesian subplots are 'xNYN' pairs like 'x2y2'; polar/geo/ternary use their own ids.
- Guard the hover call behind a check that the subplot still exists after any relayout/deletion.
- Ensure Plotly.newPlot has resolved (await it) before hover so fullLayout is populated.
Example fix
// before
Plotly.Fx.hover(gd, evt, 'x3y3'); // may not exist
// after
const spId = 'x3y3';
if (gd._fullLayout[spId] && gd._fullLayout[spId]._subplot) {
Plotly.Fx.hover(gd, evt, spId);
} Defensive patterns
Strategy: validation
Validate before calling
function subplotExists(gd, spId) {
const fl = gd && gd._fullLayout;
return !!fl && (spId === 'xy' ? !!(fl.xaxis && fl.yaxis) : !!(fl[spId] && fl[spId]._subplot));
} Type guard
function isSubplotId(spId, gd) {
return typeof spId === 'string' && subplotExists(gd, spId);
} Try / catch
if (!subplotExists(gd, spId)) {
console.warn('skipping hover, missing subplot', spId);
return;
}
Plotly.Fx.hover(gd, evt, spId); Prevention
- Derive subplot ids from gd._fullLayout._subplots instead of hard-coding.
- Re-check subplot existence after any relayout/deletes subplots.
- Use correct cartesian id format ('x2y2'), not 'xy2' or 'x3y3' guesses.
- Await Plotly.newPlot before calling hover so fullLayout is ready.
When it happens
Trigger: Calling Plotly.Fx.hover(gd, evt, 'x3y3') or another subplot id that does not exist in the graph's fullLayout — e.g. referencing x2y2 when the figure has only one x axis, or hovering a removed subplot after relayout deleted it.
Common situations: Hard-coded subplot ids that break when the figure changes shape; hover code written for a template figure reused on a smaller one; typo'd ids like 'xy2' vs 'x2y'; calling hover before the first plot completes.
Related errors
AI-assisted analysis of plotly/plotly.js@1d090e0b5f (2026-09-02).
Data as JSON: /api/errors/9a93396b82044e05.
Report an issue: GitHub.