{"record":{"id":"db321026eb543838","repo":"videojs/video.js","slug":"illegal-plugin-for-name-must-be-a-function","errorCode":null,"errorMessage":"Illegal plugin for \"${name}\", must be a function, was ${typeof plugin}.","messagePattern":"Illegal plugin for \"(.+?)\", must be a function, was (.+?)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/js/plugin.js","lineNumber":358,"sourceCode":"   *          A sub-class of `Plugin` or a function for basic plugins.\n   *\n   * @return {typeof Plugin|Function}\n   *          For advanced plugins, a factory function for that plugin. For\n   *          basic plugins, a wrapper function that initializes the plugin.\n   */\n  static registerPlugin(name, plugin) {\n    if (typeof name !== 'string') {\n      throw new Error(`Illegal plugin name, \"${name}\", must be a string, was ${typeof name}.`);\n    }\n\n    if (pluginExists(name)) {\n      log.warn(`A plugin named \"${name}\" already exists. You may want to avoid re-registering plugins!`);\n    } else if (Player.prototype.hasOwnProperty(name)) {\n      throw new Error(`Illegal plugin name, \"${name}\", cannot share a name with an existing player method!`);\n    }\n\n    if (typeof plugin !== 'function') {\n      throw new Error(`Illegal plugin for \"${name}\", must be a function, was ${typeof plugin}.`);\n    }\n\n    pluginStorage[name] = plugin;\n\n    // Add a player prototype method for all sub-classed plugins (but not for\n    // the base Plugin class).\n    if (name !== BASE_PLUGIN_NAME) {\n      if (Plugin.isBasic(plugin)) {\n        Player.prototype[name] = createBasicPlugin(name, plugin);\n      } else {\n        Player.prototype[name] = createPluginFactory(name, plugin);\n      }\n    }\n\n    return plugin;\n  }\n\n  /**","sourceCodeStart":340,"sourceCodeEnd":376,"githubUrl":"https://github.com/videojs/video.js/blob/c3a7e0e6d20cf5400c9afbee29965fe4dff393c2/src/js/plugin.js#L340-L376","documentation":"registerPlugin requires the plugin argument to be a function — either a sub-class of Plugin (advanced plugin) or a plain function (basic plugin). Non-function values cannot be invoked as plugins, and registering them would poison Player.prototype with a non-callable method. The error includes the actual typeof for quick diagnosis.","triggerScenarios":"Calling videojs.registerPlugin('x', undefined), registerPlugin('x', {}), registerPlugin('x', 42), or passing a class instance instead of the class/function reference.","commonSituations":"Forgetting the extends clause and passing an object literal; default-export confusion (passing module instead of module.default); passing an already-instantiated plugin object.","solutions":["For an advanced plugin, pass the class: videojs.registerPlugin('x', MyPluginClass) where MyPluginClass extends Plugin.","For a basic plugin, pass a function: videojs.registerPlugin('x', function(opts){...}).","Verify the import: use import MyPlugin from '...' (default) vs { MyPlugin } (named) correctly."],"exampleFix":"// before\nvideojs.registerPlugin('x', {init(){}}); // object literal\n// after\nvideojs.registerPlugin('x', function x(options) { /* basic plugin */ });","handlingStrategy":"type-guard","validationCode":"function safeRegisterPlugin(name, plugin) {\n  if (typeof plugin !== 'function') {\n    throw new TypeError(`plugin must be a function, got ${typeof plugin}`);\n  }\n  return videojs.registerPlugin(name, plugin);\n}","typeGuard":"const isPluginFn = (p) => typeof p === 'function';","tryCatchPattern":null,"preventionTips":["Confirm default vs named import paths for plugin modules.","Pass the class/function reference, never an instance or object literal.","Add a unit test that registers each plugin you ship."],"tags":["plugin","registry","validation","function"],"backgroundTag":null,"analyzedSha":"c3a7e0e6d20cf5400c9afbee29965fe4dff393c2","analyzedAt":"2026-08-13T04:20:15.471Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}