{"record":{"id":"4d3d138e7c608688","repo":"videojs/video.js","slug":"plugin-name-does-not-exist","errorCode":null,"errorMessage":"plugin \"${name}\" does not exist","messagePattern":"plugin \"(.+?)\" does not exist","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/js/player.js","lineNumber":483,"sourceCode":"\n    this.changingSrc_ = false;\n    this.playCallbacks_ = [];\n    this.playTerminatedQueue_ = [];\n\n    // the attribute overrides the option\n    if (tag.hasAttribute('autoplay')) {\n      this.autoplay(true);\n    } else {\n      // otherwise use the setter to validate and\n      // set the correct value.\n      this.autoplay(this.options_.autoplay);\n    }\n\n    // check plugins\n    if (options.plugins) {\n      Object.keys(options.plugins).forEach((name) => {\n        if (typeof this[name] !== 'function') {\n          throw new Error(`plugin \"${name}\" does not exist`);\n        }\n      });\n    }\n\n    /*\n     * Store the internal state of scrubbing\n     *\n     * @private\n     * @return {Boolean} True if the user is scrubbing\n     */\n    this.scrubbing_ = false;\n\n    this.el_ = this.createEl();\n\n    // Make this an evented object and use `el_` as its event bus.\n    evented(this, {eventBusKey: 'el_'});\n\n    // listen to document and player fullscreenchange handlers so we receive those events","sourceCodeStart":465,"sourceCodeEnd":501,"githubUrl":"https://github.com/videojs/video.js/blob/c3a7e0e6d20cf5400c9afbee29965fe4dff393c2/src/js/player.js#L465-L501","documentation":"During player init, every key in options.plugins is expected to correspond to a registered plugin method on the player instance (videojs adds plugin methods to Player.prototype at registration time). If this[name] is not a function for any plugin key, that plugin was never registered, so its configured options would be silently ignored — video.js fails fast instead.","triggerScenarios":"Calling videojs('vid', {plugins: {myPlugin: {...}}}) when 'myPlugin' was never registered via videojs.registerPlugin('myPlugin', ...); typo in plugin name; plugin script loaded after the player call.","commonSituations":"Plugin <script> tag ordered after the player init code; plugin bundled separately and tree-shaken; rename of a plugin without updating config; SSR where plugins are not registered server-side.","solutions":["Register the plugin before creating the player: videojs.registerPlugin('myPlugin', myPlugin) (or rely on the plugin's self-registering side-effect import).","Ensure the plugin script is loaded/executed before the videojs('vid', {...}) call.","Verify spelling/case of the plugin name against the registered name."],"exampleFix":"// before\nvideojs('vid', { plugins: { markers: {} } }); // markers plugin not loaded\n// after\nimport 'videojs-markers'; // side-effect: registers plugin\nvideojs('vid', { plugins: { markers: {} } });","handlingStrategy":"validation","validationCode":"function validatePluginsOption(player, options) {\n  if (!options.plugins) return;\n  Object.keys(options.plugins).forEach((name) => {\n    if (typeof player[name] !== 'function') {\n      throw new Error(`plugin '${name}' not registered before player init`);\n    }\n  });\n}","typeGuard":"const pluginIsRegistered = (name) =>\n  typeof videojs.Player.prototype[name] === 'function';","tryCatchPattern":null,"preventionTips":["Load/register plugin scripts before videojs('id', {plugins:{...}}).","Side-effect-import plugins at the top of your entry module.","Add an integration test asserting each configured plugin is registered."],"tags":["player","plugin","lifecycle","config"],"backgroundTag":null,"analyzedSha":"c3a7e0e6d20cf5400c9afbee29965fe4dff393c2","analyzedAt":"2026-08-13T04:20:15.471Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}