{"record":{"id":"b10052e85fc3e24d","repo":"greensock/GSAP","slug":"element-not-found-t","errorCode":null,"errorMessage":"Element not found: ${t}","messagePattern":"Element not found: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/Observer.js","lineNumber":57,"sourceCode":"\t\t\tif (value || value === 0) {\n\t\t\t\t_startup && (_win.history.scrollRestoration = \"manual\"); // otherwise the new position will get overwritten by the browser onload.\n\t\t\t\tlet isNormalizing = _normalizer && _normalizer.isPressed;\n\t\t\t\tvalue = cachingFunc.v = Math.round(value) || (_normalizer && _normalizer.iOS ? 1 : 0); //TODO: iOS Bug: if you allow it to go to 0, Safari can start to report super strange (wildly inaccurate) touch positions!\n\t\t\t\tf(value);\n\t\t\t\tcachingFunc.cacheID = _scrollers.cache;\n\t\t\t\tisNormalizing && _bridge(\"ss\", value); // set scroll (notify ScrollTrigger so it can dispatch a \"scrollStart\" event if necessary\n\t\t\t} else if (doNotCache || _scrollers.cache !== cachingFunc.cacheID || _bridge(\"ref\")) {\n\t\t\t\tcachingFunc.cacheID = _scrollers.cache;\n\t\t\t\tcachingFunc.v = f();\n\t\t\t}\n\t\t\treturn cachingFunc.v + cachingFunc.offset;\n\t\t};\n\t\tcachingFunc.offset = 0;\n\t\treturn f && cachingFunc;\n\t},\n\t_horizontal = {s: _scrollLeft, p: \"left\", p2: \"Left\", os: \"right\", os2: \"Right\", d: \"width\", d2: \"Width\", a: \"x\", sc: _scrollCacheFunc(function(value) { return arguments.length ? _win.scrollTo(value, _vertical.sc()) : _win.pageXOffset || _doc[_scrollLeft] || _docEl[_scrollLeft] || _body[_scrollLeft] || 0})},\n\t_vertical = {s: _scrollTop, p: \"top\", p2: \"Top\", os: \"bottom\", os2: \"Bottom\", d: \"height\", d2: \"Height\", a: \"y\", op: _horizontal, sc: _scrollCacheFunc(function(value) { return arguments.length ? _win.scrollTo(_horizontal.sc(), value) : _win.pageYOffset || _doc[_scrollTop] || _docEl[_scrollTop] || _body[_scrollTop] || 0})},\n\t_getTarget = (t, self) => ((self && self._ctx && self._ctx.selector) || gsap.utils.toArray)(t)[0] || (typeof(t) === \"string\" && gsap.config().nullTargetWarn !== false ? console.warn(\"Element not found:\", t) : null),\n\n\t_isWithin = (element, list) => { // check if the element is in the list or is a descendant of an element in the list.\n\t\tlet i = list.length;\n\t\twhile (i--) {\n\t\t\tif (list[i] === element || list[i].contains(element)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t},\n\t_getScrollFunc = (element, {s, sc}) => { // we store the scroller functions in an alternating sequenced Array like [element, verticalScrollFunc, horizontalScrollFunc, ...] so that we can minimize memory, maximize performance, and we also record the last position as a \".rec\" property in order to revert to that after refreshing to ensure things don't shift around.\n\t\t_isViewport(element) && (element = _doc.scrollingElement || _docEl);\n\t\tlet i = _scrollers.indexOf(element),\n\t\t\toffset = sc === _vertical.sc ? 1 : 2;\n\t\t!~i && (i = _scrollers.push(element) - 1);\n\t\t_scrollers[i + offset] || _addListener(element, \"scroll\", _onScroll); // clear the cache when a scroll occurs\n\t\tlet prev = _scrollers[i + offset],\n\t\t\tfunc = prev || (_scrollers[i + offset] = _scrollCacheFunc(_getProxyProp(element, s), true) || (_isViewport(element) ? sc : _scrollCacheFunc(function(value) { return arguments.length ? (element[s] = value) : element[s]; })));","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/greensock/GSAP/blob/13e2b790546426a1a2e0e9b409f3f8dc6d6611f2/src/Observer.js#L39-L75","documentation":"Observer's _getTarget helper resolves the `target` config to a DOM element via gsap.utils.toArray. When the selector/element cannot be resolved it warns \"Element not found: <t>\" and returns null (which makes Observer fall back to the document element in init). This library throws it so you know your selector matched nothing rather than silently observing the wrong element.","triggerScenarios":"new Observer({target: \"#missing\"}) or Observer.create({target: ...}) where the selector string matches no element, the element is not yet in the DOM, or a null/undefined target is passed before the DOM is ready.","commonSituations":"Running before DOMContentLoaded, typos in the selector, targeting elements rendered later by a framework (React/Vue mounts), or passing a selector scoped to a different document/iframe.","solutions":["Ensure the target element exists in the DOM before creating the Observer (wrap in DOMContentLoaded or run after framework mount)","Fix the selector string or pass an actual Element reference instead of a string","Set gsap.config({nullTargetWarn: false}) only if a missing target is expected and falling back to the document element is acceptable","Verify you are querying the correct document/iframe context"],"exampleFix":"// before\nObserver.create({ target: '#scroller', onY: y => console.log(y) });\n// after\ndocument.addEventListener('DOMContentLoaded', () => {\n  const el = document.querySelector('#scroller');\n  if (el) Observer.create({ target: el, onY: y => console.log(y) });\n});","handlingStrategy":"validation","validationCode":"const el = typeof target === 'string' ? document.querySelector(target) : target;\nif (!(el instanceof Element)) { throw new Error(`Observer target not found: ${target}`); }\nnew Observer({ target: el });","typeGuard":"function isElement(v) { return v instanceof Element; }","tryCatchPattern":null,"preventionTips":["Create observers after DOM ready / framework mount","Pass Element references instead of selector strings when possible","Centralize element lookups with a helper that asserts existence","Temporarily keep nullTargetWarn enabled in dev to catch bad selectors"],"tags":["dom","selector","observer","gsap"],"backgroundTag":"element-not-found","analyzedSha":"13e2b790546426a1a2e0e9b409f3f8dc6d6611f2","analyzedAt":"2026-08-29T08:34:05.027Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}