{"record":{"id":"e426f572004cd4c6","repo":"greensock/GSAP","slug":"error-gsdevtools-can-only-have-one-instance-that","errorCode":null,"errorMessage":"Error: GSDevTools can only have one instance that's globally synchronized.","messagePattern":"Error: GSDevTools can only have one instance that's globally synchronized\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/GSDevTools.js","lineNumber":790,"sourceCode":"\t\t\t\t\t\tdeclaredAnimation.resume();\n\t\t\t\t\t\tlinkedAnimation.kill();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tinProgress = selectedAnimation._inProgress || 0;\n\t\t\t\toutProgress = selectedAnimation._outProgress || 100;\n\t\t\t\tinPoint.style.left = inProgress + \"%\";\n\t\t\t\toutPoint.style.left = outProgress + \"%\";\n\t\t\t\tif (_fullyInitialized) { //don't record inProgress/outProgress unless we're fully instantiated because people may call GSDevTools.create() before creating/defining their animations, thus the inTime/outTime may not exist yet.\n\t\t\t\t\trecord(\"animation\", selectedAnimation.vars.id);\n\t\t\t\t\trecord(\"in\", inProgress);\n\t\t\t\t\trecord(\"out\", outProgress);\n\t\t\t\t}\n\t\t\t\tstartTime = 0;\n\t\t\t\tmaxDuration = vars.maxDuration || Math.min(1000, _getClippedDuration(selectedAnimation));\n\t\t\t\tif (selectedAnimation === _recordedRoot || vars.globalSync) {\n\t\t\t\t\t_merge();\n\t\t\t\t\tlinkedAnimation = _rootTween;\n\t\t\t\t\t_rootInstance && _rootInstance !== _self && console.warn(\"Error: GSDevTools can only have one instance that's globally synchronized.\");\n\t\t\t\t\t_rootInstance = _self;\n\t\t\t\t\tif (selectedAnimation !== _recordedRoot) {\n\t\t\t\t\t\ttl = selectedAnimation;\n\t\t\t\t\t\tendTime = tl.totalDuration();\n\t\t\t\t\t\tif (endTime > 99999999) { //in the case of an infinitely repeating animation, just use a single iteration's duration instead.\n\t\t\t\t\t\t\tendTime = tl.duration();\n\t\t\t\t\t\t}\n\t\t\t\t\t\twhile (tl.parent) {\n\t\t\t\t\t\t\tstartTime = (startTime / tl._ts) + tl._start;\n\t\t\t\t\t\t\tendTime = (endTime / tl._ts) + tl._start;\n\t\t\t\t\t\t\ttl = tl.parent;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tendTime = _recordedRoot.duration();\n\t\t\t\t\t}\n\t\t\t\t\tif (endTime - startTime > maxDuration) { //cap end time at 1000 because it doesn't seem reasonable to accommodate super long stuff.\n\t\t\t\t\t\tendTime = startTime + maxDuration;\n\t\t\t\t\t}","sourceCodeStart":772,"sourceCodeEnd":808,"githubUrl":"https://github.com/greensock/GSAP/blob/13e2b790546426a1a2e0e9b409f3f8dc6d6611f2/src/GSDevTools.js#L772-L808","documentation":"GSDevTools synchronizes all instances through a single hidden root tween; only one instance can own that global sync at a time. Creating a second instance with vars.globalSync (true by default, or when animating the _recordedRoot) warns that the previous instance loses sync ownership.","triggerScenarios":"Calling GSDevTools.create() twice with globalSync not disabled; creating instances in multiple components/pages that each default to globalSync; leaving an old instance alive when mounting a new one (e.g. in React/HMR re-renders).","commonSituations":"React strict-mode or HMR double-mounting a component that calls GSDevTools.create(); opening the tool on the global timeline in several widgets on one page; SPA navigation without killing the previous instance.","solutions":["Kill the previous instance before creating a new one (GSDevTools.getByAnimation(animation).kill() or instance.kill())","Set globalSync:false on all but one instance","Guard creation so only one instance exists app-wide (module-level singleton)"],"exampleFix":"// before\nclass Panel { mount() { this.devTools = GSDevTools.create({ animation: tl }); } }\n// after\nclass Panel {\n  mount() {\n    this.devTools?.kill?.();\n    const existing = GSDevTools.getByAnimation(tl);\n    if (existing) existing.kill();\n    this.devTools = GSDevTools.create({ animation: tl, globalSync: false });\n  }\n}","handlingStrategy":"validation","validationCode":"if (GSDevTools.getByAnimation(animation)) { /* instance exists */ } else { GSDevTools.create({ animation }); }","typeGuard":"const hasActiveGlobalInstance = () => !!document.querySelector('.gs-dev-tools');","tryCatchPattern":null,"preventionTips":["Kill GSDevTools instances on component unmount","Use a module-level singleton for the tool","Set globalSync:false for secondary instances","Watch for React StrictMode/HMR double-mounts"],"tags":["gsap","singleton","global-state"],"backgroundTag":"singleton-instance-conflict","analyzedSha":"13e2b790546426a1a2e0e9b409f3f8dc6d6611f2","analyzedAt":"2026-08-29T08:34:05.027Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}