videojs/video.js · error · Error
Invalid target for ${objName(obj)}#${fnName}; must be a DOM
Error message
Invalid target for ${objName(obj)}#${fnName}; must be a DOM node or evented object. What it means
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.
Source
Thrown at src/js/mixins/evented.js:99
/**
* Validates a value to determine if it is a valid event target. Throws if not.
*
* @private
* @throws {Error}
* If the target does not appear to be a valid event target.
*
* @param {Object} target
* The object to test.
*
* @param {Object} obj
* The evented object we are validating for
*
* @param {string} fnName
* The name of the evented mixin function that called this.
*/
const validateTarget = (target, obj, fnName) => {
if (!target || (!target.nodeName && !isEvented(target))) {
throw new Error(`Invalid target for ${objName(obj)}#${fnName}; must be a DOM node or evented object.`);
}
};
/**
* Validates a value to determine if it is a valid event target. Throws if not.
*
* @private
* @throws {Error}
* If the type does not appear to be a valid event type.
*
* @param {string|Array} type
* The type to test.
*
* @param {Object} obj
* The evented object we are validating for
*
* @param {string} fnName
* The name of the evented mixin function that called this.View on GitHub (pinned to c3a7e0e6d2)
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.
Example fix
// before
player.on({handleEvent(){}}, 'play', fn); // plain object
// after
const target = document.querySelector('#btn');
player.on(target, 'click', fn); Defensive patterns
Strategy: type-guard
Validate before calling
function isValidEventTarget(t) {
return Boolean(t && (t.nodeName || videojs.obj && videojs.obj.isEvented && videojs.obj.isEvented(t)));
}
if (!isValidEventTarget(target)) throw new TypeError('bad event target'); Type guard
const isEventTarget = (t) => Boolean(t) && (typeof t.nodeName === 'string' || videojs.obj.isEvented(t));
Prevention
- 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.
When it happens
Trigger: Calling component.on(plainObj, 'click', fn), component.off({}, ...), or component.trigger(null) where the target is neither a DOM node nor an evented object.
Common situations: 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.
Related errors
- Invalid event type for ${objName(obj)}#${fnName}; must be a
- Invalid listener for ${objName(obj)}#${fnName}; must be a fu
- Invalid event type for ${objName(this)}#trigger; must be a n
- The eventBusKey "${eventBusKey}" does not refer to an elemen
- currentDimension only accepts width or height value
AI-assisted analysis of videojs/video.js@c3a7e0e6d2 (2026-08-13).
Data as JSON: /api/errors/1b84fe4ddba5b835.
Report an issue: GitHub.