{"record":{"id":"1b84fe4ddba5b835","repo":"videojs/video.js","slug":"invalid-target-for-objname-obj-fnname-must","errorCode":null,"errorMessage":"Invalid target for ${objName(obj)}#${fnName}; must be a DOM node or evented object.","messagePattern":"Invalid target for (.+?)#(.+?); must be a DOM node or evented object\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/js/mixins/evented.js","lineNumber":99,"sourceCode":"/**\n * Validates a value to determine if it is a valid event target. Throws if not.\n *\n * @private\n * @throws {Error}\n *         If the target does not appear to be a valid event target.\n *\n * @param  {Object} target\n *         The object to test.\n *\n * @param  {Object} obj\n *         The evented object we are validating for\n *\n * @param  {string} fnName\n *         The name of the evented mixin function that called this.\n */\nconst validateTarget = (target, obj, fnName) => {\n  if (!target || (!target.nodeName && !isEvented(target))) {\n    throw new Error(`Invalid target for ${objName(obj)}#${fnName}; must be a DOM node or evented object.`);\n  }\n};\n\n/**\n * Validates a value to determine if it is a valid event target. Throws if not.\n *\n * @private\n * @throws {Error}\n *         If the type does not appear to be a valid event type.\n *\n * @param  {string|Array} type\n *         The type to test.\n *\n * @param  {Object} obj\n*         The evented object we are validating for\n *\n * @param  {string} fnName\n *         The name of the evented mixin function that called this.","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/videojs/video.js/blob/c3a7e0e6d20cf5400c9afbee29965fe4dff393c2/src/js/mixins/evented.js#L81-L117","documentation":"The evented mixin (on/one/off/trigger) only operates on targets that are DOM nodes (have a nodeName) or objects already mixed-in with evented (isEvented). This prevents silently attaching listeners to plain objects that have no event bus element. The error names the calling object and method (objName#fnName) for quick localization.","triggerScenarios":"Calling component.on(plainObj, 'click', fn), component.off({}, ...), or component.trigger(null) where the target is neither a DOM node nor an evented object.","commonSituations":"Passing a jQuery wrapper, a plain config object, or a DOM selector string instead of an element; mixing video.js events with another library's objects; refactoring that loses the el reference.","solutions":["Pass the DOM element directly: component.on(el, 'click', fn).","Make the target evented first: videojs.obj.evented(target) (or apply evented() in your class) before using it as a target.","If you only need self-events, call on('type', fn) with no target — the component's own eventBusEl_ is used."],"exampleFix":"// before\nplayer.on({handleEvent(){}}, 'play', fn); // plain object\n// after\nconst target = document.querySelector('#btn');\nplayer.on(target, 'click', fn);","handlingStrategy":"type-guard","validationCode":"function isValidEventTarget(t) {\n  return Boolean(t && (t.nodeName || videojs.obj && videojs.obj.isEvented && videojs.obj.isEvented(t)));\n}\nif (!isValidEventTarget(target)) throw new TypeError('bad event target');","typeGuard":"const isEventTarget = (t) =>\n  Boolean(t) && (typeof t.nodeName === 'string' || videojs.obj.isEvented(t));","tryCatchPattern":null,"preventionTips":["Pass DOM elements directly, never selectors or jQuery objects.","Call on('type', fn) for self-events to skip target validation.","Apply evented() to objects you intend to use as targets."],"tags":["events","evented","validation","dom"],"backgroundTag":null,"analyzedSha":"c3a7e0e6d20cf5400c9afbee29965fe4dff393c2","analyzedAt":"2026-08-13T04:20:15.471Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}