facebook/docusaurus · error · Error
Plugin "${pluginName}" is used ${pluginInstancesWithId.lengt
Error message
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).` : ''} What it means
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.
Source
Thrown at packages/docusaurus/src/server/plugins/pluginIds.ts:28
import type {InitializedPlugin} from '@docusaurus/types';
/**
* It is forbidden to have 2 plugins of the same name sharing the same ID.
* This is required to support multi-instance plugins without conflict.
*/
export function ensureUniquePluginInstanceIds(
plugins: InitializedPlugin[],
): void {
const pluginsByName = _.groupBy(plugins, (p) => p.name);
Object.entries(pluginsByName).forEach(([pluginName, pluginInstances]) => {
const pluginInstancesById = _.groupBy(
pluginInstances,
(p) => p.options.id ?? DEFAULT_PLUGIN_ID,
);
Object.entries(pluginInstancesById).forEach(
([pluginId, pluginInstancesWithId]) => {
if (pluginInstancesWithId.length !== 1) {
throw new Error(
`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).`
: ''
}`,
);
}
},
);
});
}
View on GitHub (pinned to 3f483e80e3)
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.
Example fix
// before
presets: [['classic', {}]],
plugins: [['@docusaurus/plugin-content-docs', {path: 'other-docs'}]],
// after
presets: [['classic', {}]],
plugins: [['@docusaurus/plugin-content-docs', {id: 'other', path: 'other-docs'}]], Defensive patterns
Strategy: validation
Validate before calling
function assertUniqueIds(plugins: Array<{name: string; options: {id?: string}}>) {
const seen = new Set<string>();
for (const p of plugins) {
const key = `${p.name}:${p.options.id ?? 'default'}`;
if (seen.has(key)) throw new Error(`Duplicate plugin id: ${key}`);
seen.add(key);
}
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- A Docusaurus plugin returned 'undefined', which is forbidden
- A Docusaurus plugin is missing a 'name' property.\nNote that
- Docusaurus was unable to resolve the "${moduleName}" ${modul
- Plugin not found for identifier ${formatPluginName(pluginIde
- Translation file path at "${translationFilePath}" does not n
AI-assisted analysis of facebook/docusaurus@3f483e80e3 (2026-08-12).
Data as JSON: /api/errors/a9ed24c4cf00368c.
Report an issue: GitHub.