{"record":{"id":"a9ed24c4cf00368c","repo":"facebook/docusaurus","slug":"plugin-pluginname-is-used-plugininstanceswi","errorCode":null,"errorMessage":"Plugin \"${pluginName}\" is used ${pluginInstancesWithId.length} times with ID \"${pluginId}\".\\nTo use the same plugin multiple times on a Docusaurus site, you need to assign a unique ID to each plugin instance.${pluginId === DEFAULT_PLUGIN_ID ? `\\n\\nThe plugin ID is \"${DEFAULT_PLUGIN_ID}\" by default. It's possible that the preset you are using already includes a plugin instance, in which case you either want to disable the plugin in the preset (to use a single instance), or assign another ID to your extra plugin instance (to use multiple instances).` : ''}","messagePattern":"Plugin \"(.+?)\" is used (.+?) times with ID \"(.+?)\"\\.\\\\nTo use the same plugin multiple times on a Docusaurus site, you need to assign a unique ID to each plugin instance\\.(.+?)\" by default\\. It's possible that the preset you are using already includes a plugin instance, in which case you either want to disable the plugin in the preset \\(to use a single instance\\), or assign another ID to your extra plugin instance \\(to use multiple instances\\)\\.` : ''\\}","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/docusaurus/src/server/plugins/pluginIds.ts","lineNumber":28,"sourceCode":"import type {InitializedPlugin} from '@docusaurus/types';\n\n/**\n * It is forbidden to have 2 plugins of the same name sharing the same ID.\n * This is required to support multi-instance plugins without conflict.\n */\nexport function ensureUniquePluginInstanceIds(\n  plugins: InitializedPlugin[],\n): void {\n  const pluginsByName = _.groupBy(plugins, (p) => p.name);\n  Object.entries(pluginsByName).forEach(([pluginName, pluginInstances]) => {\n    const pluginInstancesById = _.groupBy(\n      pluginInstances,\n      (p) => p.options.id ?? DEFAULT_PLUGIN_ID,\n    );\n    Object.entries(pluginInstancesById).forEach(\n      ([pluginId, pluginInstancesWithId]) => {\n        if (pluginInstancesWithId.length !== 1) {\n          throw new Error(\n            `Plugin \"${pluginName}\" is used ${\n              pluginInstancesWithId.length\n            } times with ID \"${pluginId}\".\\nTo use the same plugin multiple times on a Docusaurus site, you need to assign a unique ID to each plugin instance.${\n              pluginId === DEFAULT_PLUGIN_ID\n                ? `\\n\\nThe plugin ID is \"${DEFAULT_PLUGIN_ID}\" by default. It's possible that the preset you are using already includes a plugin instance, in which case you either want to disable the plugin in the preset (to use a single instance), or assign another ID to your extra plugin instance (to use multiple instances).`\n                : ''\n            }`,\n          );\n        }\n      },\n    );\n  });\n}\n","sourceCodeStart":10,"sourceCodeEnd":42,"githubUrl":"https://github.com/facebook/docusaurus/blob/3f483e80e326cc646b54b83d564b3f0c4881b9a6/packages/docusaurus/src/server/plugins/pluginIds.ts#L10-L42","documentation":"Thrown by `ensureUniquePluginInstanceIds` after initialization when two or more loaded plugins share the same `name` AND the same `options.id` (defaulting to `'default'`). Docusaurus needs each plugin instance to have a unique (name, id) tuple to namespace data and routes. The message specially hints when the collision is on the default id, since that often means a preset already registered the plugin.","triggerScenarios":"Listing the same plugin twice without distinct `id` options; adding a plugin in `plugins:` that a preset already injects under the default id. The check at pluginIds.ts:25-44 groups by name then by id and throws when a group has length !== 1.","commonSituations":"Using `@docusaurus/plugin-content-docs` both via preset-classic and again explicitly; multi-instance plugins (blog, docs) where the user forgot `id: 'secondary'`; copying a plugin entry in config.","solutions":["Give each duplicate instance a unique `id` in its options (e.g. `{id: 'community', path: 'community/docs'}`).","If you only want one instance, disable the preset's copy (e.g. `presets: [['classic', {docs: false}]]`) and keep your explicit one.","Remove the redundant plugin entry entirely."],"exampleFix":"// before\npresets: [['classic', {}]],\nplugins: [['@docusaurus/plugin-content-docs', {path: 'other-docs'}]],\n// after\npresets: [['classic', {}]],\nplugins: [['@docusaurus/plugin-content-docs', {id: 'other', path: 'other-docs'}]],","handlingStrategy":"validation","validationCode":"function assertUniqueIds(plugins: Array<{name: string; options: {id?: string}}>) {\n  const seen = new Set<string>();\n  for (const p of plugins) {\n    const key = `${p.name}:${p.options.id ?? 'default'}`;\n    if (seen.has(key)) throw new Error(`Duplicate plugin id: ${key}`);\n    seen.add(key);\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Assign explicit `id` to every multi-instance plugin (docs, blog).","When adding a plugin a preset already provides, disable it in the preset first.","Keep a single source of truth for plugin ids in config."],"tags":["plugins","config","uniqueness","presets"],"backgroundTag":null,"analyzedSha":"3f483e80e326cc646b54b83d564b3f0c4881b9a6","analyzedAt":"2026-08-12T13:25:04.382Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}