{"record":{"id":"abf6550ad51462e9","repo":"plotly/plotly.js","slug":"trace-index-index-is-not-a-number-or-is-out","errorCode":null,"errorMessage":"trace index ( ${index} ) is not a number or is out of bounds","messagePattern":"trace index \\( (.+?) \\) is not a number or is out of bounds","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/plot_api/helpers.js","lineNumber":386,"sourceCode":"        trace.hoverinfo = hoverInfoParts.join('+');\n    }\n};\n\n// coerce traceIndices input to array of trace indices\nexports.coerceTraceIndices = function (gd, traceIndices) {\n    if (isNumeric(traceIndices)) {\n        return [traceIndices];\n    } else if (!Array.isArray(traceIndices) || !traceIndices.length) {\n        return gd.data.map(function (_, i) {\n            return i;\n        });\n    } else if (Array.isArray(traceIndices)) {\n        var traceIndicesOut = [];\n        for (var i = 0; i < traceIndices.length; i++) {\n            if (Lib.isIndex(traceIndices[i], gd.data.length)) {\n                traceIndicesOut.push(traceIndices[i]);\n            } else {\n                Lib.warn('trace index (', traceIndices[i], ') is not a number or is out of bounds');\n            }\n        }\n        return traceIndicesOut;\n    }\n\n    return traceIndices;\n};\n\n/**\n * Manages logic around array container item creation / deletion / update\n * that nested property alone can't handle.\n *\n * @param {Object} np\n *  nested property of update attribute string about trace or layout object\n * @param {*} newVal\n *  update value passed to restyle / relayout / update\n * @param {Object} undoit\n *  undo hash (N.B. undoit may be mutated here).","sourceCodeStart":368,"sourceCodeEnd":404,"githubUrl":"https://github.com/plotly/plotly.js/blob/1d090e0b5ffb8d0fdf6e0e4ff51d3f3cf67f1314/src/plot_api/helpers.js#L368-L404","documentation":"Helpers that operate on traces (e.g. deleteTraces, moveTraces, extend/prepend traces) validate each requested trace index with Lib.isIndex against gd.data.length. A non-numeric or out-of-bounds entry is reported via this warning and silently dropped from the resulting index list instead of throwing.","triggerScenarios":"Calling Plotly.deleteTraces(gd, [0, 5]) when gd.data has fewer than 6 traces, passing a string like '1' or null/undefined as an index, or passing an index computed from stale state after a previous deletion.","commonSituations":"React/Vue apps keeping stale trace indices after data updates, user-driven deletion buttons acting twice (double click), and off-by-one loops over trace arrays.","solutions":["Validate indices before the call: 0 <= i < gd.data.length and typeof i === 'number'.","Refresh any cached indices from gd.data immediately before operating on traces.","Debounce/double-submit-guard UI actions that delete or move traces.","Pass trace UIDs or objects instead of raw indices where the API accepts them, to avoid stale-position bugs."],"exampleFix":"// before\nPlotly.deleteTraces(gd, [idx]); // idx may be stale/NaN\n// after\nif (Number.isInteger(idx) && idx >= 0 && idx < gd.data.length) {\n  Plotly.deleteTraces(gd, [idx]);\n}","handlingStrategy":"type-guard","validationCode":"function validTraceIndices(gd, idxs) {\n  return (Array.isArray(idxs) ? idxs : [idxs])\n    .filter(i => Number.isInteger(i) && i >= 0 && i < gd.data.length);\n}","typeGuard":"function isValidTraceIndex(i, gd) { return Number.isInteger(i) && i >= 0 && i < gd.data.length; }","tryCatchPattern":null,"preventionTips":["Recompute indices from gd.data immediately before trace operations.","Filter arrays of indices with isValidTraceIndex before passing them.","Guard UI delete/move actions against double submission.","Prefer trace uids over positional indices for long-lived references."],"tags":["traces","index-out-of-bounds","argument-validation"],"backgroundTag":"index-out-of-range","analyzedSha":"1d090e0b5ffb8d0fdf6e0e4ff51d3f3cf67f1314","analyzedAt":"2026-09-02T22:03:39.906Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}