{"record":{"id":"21c90a943bdfea8a","repo":"videojs/video.js","slug":"invalid-event-type-for-objname-obj-fnname","errorCode":null,"errorMessage":"Invalid event type for ${objName(obj)}#${fnName}; must be a non-empty string or array.","messagePattern":"Invalid event type for (.+?)#(.+?); must be a non-empty string or array\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/js/mixins/evented.js","lineNumber":121,"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 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.\n */\nconst validateEventType = (type, obj, fnName) => {\n  if (!isValidEventType(type)) {\n    throw new Error(`Invalid event type for ${objName(obj)}#${fnName}; must be a non-empty string or array.`);\n  }\n};\n\n/**\n * Validates a value to determine if it is a valid listener. Throws if not.\n *\n * @private\n * @throws {Error}\n *         If the listener is not a function.\n *\n * @param  {Function} listener\n *         The listener 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":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/videojs/video.js/blob/c3a7e0e6d20cf5400c9afbee29965fe4dff393c2/src/js/mixins/evented.js#L103-L139","documentation":"validateEventType rejects empty strings, null, undefined, or non-string/non-array values passed as the event type to on()/one(). Events are dispatched by type, so an empty or malformed type would never fire and silently break handlers. Arrays are allowed for multi-type binding but must themselves contain valid types.","triggerScenarios":"Calling obj.on('', fn), obj.on(null, fn), obj.on(42, fn), or obj.on([], fn) (empty array).","commonSituations":"Building event names dynamically from data that may be empty; refactoring a constant that became undefined; passing a destructured value that was not set.","solutions":["Ensure the type is a non-empty string like 'click' or 'timeupdate'.","When using computed names, default and validate: const type = rawType || 'click'.","For multi-event binding, pass a non-empty array: obj.on(['play','pause'], fn)."],"exampleFix":"// before\nplayer.on(this.config.eventName, fn); // eventName is ''\n// after\nconst eventName = this.config.eventName || 'timeupdate';\nplayer.on(eventName, fn);","handlingStrategy":"validation","validationCode":"function isValidEventType(t) {\n  return typeof t === 'string' && t.length > 0 || Array.isArray(t) && t.length > 0;\n}\nif (!isValidEventType(type)) throw new TypeError('bad event type');","typeGuard":"const isValidEventType = (t) =>\n  (typeof t === 'string' && t.length > 0) || (Array.isArray(t) && t.length > 0);","tryCatchPattern":null,"preventionTips":["Default computed event names to a known constant.","Whitelist dynamic event types before binding.","Prefer non-empty arrays for multi-type binding."],"tags":["events","evented","validation"],"backgroundTag":null,"analyzedSha":"c3a7e0e6d20cf5400c9afbee29965fe4dff393c2","analyzedAt":"2026-08-13T04:20:15.471Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}