{"record":{"id":"f61a9ca0bcee0a7f","repo":"plotly/plotly.js","slug":"animate-failure-frame-not-found-framename","errorCode":null,"errorMessage":"animate failure: frame not found: \"${frameName}\"","messagePattern":"animate failure: frame not found: \"(.+?)\"","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/plot_api/plot_api.js","lineNumber":3338,"sourceCode":"                    frameList.push({\n                        type: 'byname',\n                        name: frameOrName,\n                        data: setTransitionConfig({ name: frameOrName })\n                    });\n                } else if (Lib.isPlainObject(frameOrName)) {\n                    frameList.push({\n                        type: 'object',\n                        data: setTransitionConfig(Lib.extendFlat({}, frameOrName))\n                    });\n                }\n            }\n        }\n\n        // Verify that all of these frames actually exist; return and reject if not:\n        for (i = 0; i < frameList.length; i++) {\n            frame = frameList[i];\n            if (frame.type === 'byname' && !trans._frameHash[frame.data.name]) {\n                Lib.warn('animate failure: frame not found: \"' + frame.data.name + '\"');\n                reject();\n                return;\n            }\n        }\n\n        // If the mode is either next or immediate, then all currently queued frames must\n        // be dumped and the corresponding .animate promises rejected.\n        if (['next', 'immediate'].indexOf(animationOpts.mode) !== -1) {\n            discardExistingFrames();\n        }\n\n        if (animationOpts.direction === 'reverse') {\n            frameList.reverse();\n        }\n\n        var currentFrame = gd._fullLayout._currentFrame;\n        if (currentFrame && animationOpts.fromcurrent) {\n            var idx = -1;","sourceCodeStart":3320,"sourceCodeEnd":3356,"githubUrl":"https://github.com/plotly/plotly.js/blob/1d090e0b5ffb8d0fdf6e0e4ff51d3f3cf67f1314/src/plot_api/plot_api.js#L3320-L3356","documentation":"Plotly.animate was asked to animate a frame by name that does not exist in the graph's frame registry (_frameHash). The animate call validates every requested 'byname' frame up front and rejects the returned promise without animating if any is missing. Frames must be registered via Plotly.addFrames (or passed inline) before they can be animated by name.","triggerScenarios":"Plotly.animate(gd, 'myFrame', ...) where 'myFrame' was never added via Plotly.addFrames; referencing a frame after Plotly.newPlot/Plotly.react recreated the graph div (frames are per-div state); typo or case mismatch in the frame name; number-vs-string name coercion making the lookup miss.","commonSituations":"Tutorials where frame names were never registered; SPA route changes recreating the plot while animating frames from the previous div; frames added to a different graph div; numeric frame names colliding with string keys.","solutions":["Register the frame before animating: await Plotly.addFrames(gd, [{name: 'myFrame', data: {...}}]) then call Plotly.animate.","Attach a .catch to the animate promise so the rejection is handled gracefully.","Confirm the frames were added to the same graph div being animated; re-add frames after any newPlot/react call.","Inspect the registered frame names (gd._transitionData._frameHash) to verify the exact name string."],"exampleFix":"// before\nPlotly.animate(gd, 'frame2', {transition: {duration: 500}});\n// after\nPlotly.addFrames(gd, [{name: 'frame2', data: [{x: [1,2,3], y: [2,4,6]}]}])\n  .then(() => Plotly.animate(gd, 'frame2', {transition: {duration: 500}}))\n  .catch(err => console.warn('animation skipped:', err));","handlingStrategy":"try-catch","validationCode":"function frameExists(gd, name) {\n  const hash = (gd._transitionData && gd._transitionData._frameHash) || {};\n  return Object.prototype.hasOwnProperty.call(hash, String(name));\n}\n// usage: if (frameExists(gd, 'frame2')) Plotly.animate(gd, 'frame2', opts);","typeGuard":"function isRegisteredFrameName(name, gd) {\n  return typeof name === 'string' &&\n    !!gd._transitionData &&\n    !!gd._transitionData._frameHash[name];\n}","tryCatchPattern":"Plotly.animate(gd, frameName, opts)\n  .then(function () { /* animation complete */ })\n  .catch(function (err) {\n    console.warn('Animation skipped, frame missing:', frameName, err);\n  });","preventionTips":["Always addFrames before animating by name.","Re-add frames after any newPlot/react call; frames are per-graph-div.","Use String() for frame names to avoid number/string coercion mismatches.","List registered frame names at runtime to verify before animating."],"tags":["plotly","animate","frames","missing-resource","promise-rejection"],"backgroundTag":"frame-not-found","analyzedSha":"1d090e0b5ffb8d0fdf6e0e4ff51d3f3cf67f1314","analyzedAt":"2026-09-02T22:03:39.906Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}