{"record":{"id":"ee890eec046a84b1","repo":"videojs/video.js","slug":"cannot-de-register-base-plugin","errorCode":null,"errorMessage":"Cannot de-register base plugin.","messagePattern":"Cannot de-register base plugin\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/js/plugin.js","lineNumber":388,"sourceCode":"      }\n    }\n\n    return plugin;\n  }\n\n  /**\n   * De-register a Video.js plugin.\n   *\n   * @param  {string} name\n   *         The name of the plugin to be de-registered. Must be a string that\n   *         matches an existing plugin.\n   *\n   * @throws {Error}\n   *         If an attempt is made to de-register the base plugin.\n   */\n  static deregisterPlugin(name) {\n    if (name === BASE_PLUGIN_NAME) {\n      throw new Error('Cannot de-register base plugin.');\n    }\n    if (pluginExists(name)) {\n      delete pluginStorage[name];\n      delete Player.prototype[name];\n    }\n  }\n\n  /**\n   * Gets an object containing multiple Video.js plugins.\n   *\n   * @param   {Array} [names]\n   *          If provided, should be an array of plugin names. Defaults to _all_\n   *          plugin names.\n   *\n   * @return {Object|undefined}\n   *          An object containing plugin(s) associated with their name(s) or\n   *          `undefined` if no matching plugins exist).\n   */","sourceCodeStart":370,"sourceCodeEnd":406,"githubUrl":"https://github.com/videojs/video.js/blob/c3a7e0e6d20cf5400c9afbee29965fe4dff393c2/src/js/plugin.js#L370-L406","documentation":"deregisterPlugin refuses to remove the base 'plugin' name (BASE_PLUGIN_NAME) because it is the abstract parent every advanced plugin extends; removing it would break subclass instantiation and the getPlugin('plugin') lookup. All other plugins can be de-registered freely. The check happens before any deletion.","triggerScenarios":"Calling videojs.deregisterPlugin('plugin') explicitly; a generic cleanup loop that de-registers every name returned by getPlugins() including the base.","commonSituations":"HMR teardown loops; test cleanup that iterates all plugins; tooling that de-registers by name without filtering.","solutions":["Skip the base name when de-registering: if (name !== 'plugin') videojs.deregisterPlugin(name).","Filter getPlugins() output to exclude 'plugin' before bulk de-registration.","Only de-register plugins you actually registered."],"exampleFix":"// before\nObject.keys(videojs.getPlugins()).forEach(n => videojs.deregisterPlugin(n)); // throws on 'plugin'\n// after\nObject.keys(videojs.getPlugins())\n  .filter(n => n !== 'plugin')\n  .forEach(n => videojs.deregisterPlugin(n));","handlingStrategy":"validation","validationCode":"function safeDeregister(name) {\n  if (name === 'plugin') throw new Error('cannot de-register base plugin');\n  videojs.deregisterPlugin(name);\n}\n// bulk cleanup\nObject.keys(videojs.getPlugins())\n  .filter((n) => n !== 'plugin')\n  .forEach((n) => videojs.deregisterPlugin(n));","typeGuard":"const isDeregisterable = (name) => typeof name === 'string' && name !== 'plugin';","tryCatchPattern":null,"preventionTips":["Always exclude 'plugin' from bulk de-registration loops.","Only de-register plugins you registered.","Track your own registered names in test/HMR teardown."],"tags":["plugin","registry","lifecycle","cleanup"],"backgroundTag":null,"analyzedSha":"c3a7e0e6d20cf5400c9afbee29965fe4dff393c2","analyzedAt":"2026-08-13T04:20:15.471Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}