{"record":{"id":"40b4e7aa574bd514","repo":"plotly/plotly.js","slug":"warning-addframes-accepts-frames-with-numeric-nam","errorCode":null,"errorMessage":"Warning: addFrames accepts frames with numeric names, but the numbers areimplicitly cast to strings","messagePattern":"Warning: addFrames accepts frames with numeric names, but the numbers areimplicitly cast to strings","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/plot_api/plot_api.js","lineNumber":3502,"sourceCode":"        });\n    }\n\n    // Sort this, taking note that undefined insertions end up at the end:\n    insertions.sort(function (a, b) {\n        if (a.index > b.index) return -1;\n        if (a.index < b.index) return 1;\n        return 0;\n    });\n\n    var ops = [];\n    var revops = [];\n    var frameCount = _frames.length;\n\n    for (i = insertions.length - 1; i >= 0; i--) {\n        frame = insertions[i].frame;\n\n        if (typeof frame.name === 'number') {\n            Lib.warn(\n                'Warning: addFrames accepts frames with numeric names, but the numbers are' +\n                    'implicitly cast to strings'\n            );\n        }\n\n        if (!frame.name) {\n            // Repeatedly assign a default name, incrementing the counter each time until\n            // we get a name that's not in the hashed lookup table:\n            while (_frameHash[(frame.name = 'frame ' + gd._transitionData._counter++)]);\n        }\n\n        if (_frameHash[frame.name]) {\n            // If frame is present, overwrite its definition:\n            for (j = 0; j < _frames.length; j++) {\n                if ((_frames[j] || {}).name === frame.name) break;\n            }\n            ops.push({ type: 'replace', index: j, value: frame });\n            revops.unshift({ type: 'replace', index: j, value: _frames[j] });","sourceCodeStart":3484,"sourceCodeEnd":3520,"githubUrl":"https://github.com/plotly/plotly.js/blob/1d090e0b5ffb8d0fdf6e0e4ff51d3f3cf67f1314/src/plot_api/plot_api.js#L3484-L3520","documentation":"Plotly.addFrames() emits this warning when a frame's `name` is a number. Frame names are used as string keys for frame lookup and ordering, so numeric names are implicitly cast to strings (e.g. 1 becomes \"1\"), which can surprise users comparing names. It is a heads-up about silent type coercion, not a failure.","triggerScenarios":"Calling Plotly.addFrames(gd, [{name: 1, data: {...}}, ...]) or passing frame objects built from numeric IDs, JSON data where names were not quoted, or generated frames whose names come from loop counters.","commonSituations":"Programmatically generating frames from numeric sequence numbers or database IDs; loading frames from JSON where names were numeric; migrating code that relied on numeric ordering by name.","solutions":["Convert frame names to strings before calling addFrames: name: String(1) or name: '1'.","If ordering matters, zero-pad string names (e.g. '001') since frame ordering/name comparison is lexicographic on strings.","If the number is only a label, keep it numeric but accept the warning; behavior is unchanged apart from the cast."],"exampleFix":"// before\nPlotly.addFrames(gd, [{name: 1, data: [{x: [1], y: [1]}]}]);\n// after\nPlotly.addFrames(gd, [{name: '1', data: [{x: [1], y: [1]}]}]);","handlingStrategy":"validation","validationCode":"function validateFrameNames(frames) {\n  frames.forEach((f, i) => {\n    if (typeof f.name === 'number') throw new TypeError(`frames[${i}].name must be a string, got number ${f.name}`);\n  });\n}\n// run before: validateFrameNames(myFrames); Plotly.addFrames(gd, myFrames);","typeGuard":"function isStringFrameName(f) { return typeof f.name === 'string'; }\nconst safe = frames.filter(isStringFrameName);","tryCatchPattern":null,"preventionTips":["Always build frame names with String(i) when deriving them from numbers.","Zero-pad numeric names if lexicographic ordering matters.","Lint JSON frame definitions for unquoted numeric names.","Document frame names as string keys in your data pipeline."],"tags":["deprecation","type-coercion","frames"],"backgroundTag":"implicit-type-coercion-warning","analyzedSha":"1d090e0b5ffb8d0fdf6e0e4ff51d3f3cf67f1314","analyzedAt":"2026-09-02T22:03:39.906Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}