facebook/docusaurus · error · Error

Docusaurus was unable to resolve the "${moduleName}" ${modul

Error message

Docusaurus was unable to resolve the "${moduleName}" ${moduleType}. Make sure one of the following packages are installed:\n${modulePatterns.map((m) => `- ${m}`).join('\n')}

What it means

Thrown by `resolveModuleName` when none of the generated name patterns for a preset/theme/plugin resolve via `require.resolve`. Docusaurus expands a shorthand name (e.g. `'classic'`) into candidate package names and tries each; if all fail, it reports the full candidate list so the user knows exactly which package to install.

Source

Thrown at packages/docusaurus/src/server/plugins/moduleShorthand.ts:48

  ];
}

export function resolveModuleName(
  moduleName: string,
  moduleRequire: NodeRequire,
  moduleType: 'preset' | 'theme' | 'plugin',
): string {
  const modulePatterns = getNamePatterns(moduleName, moduleType);
  const module = modulePatterns.find((m) => {
    try {
      moduleRequire.resolve(m);
      return true;
    } catch {
      return false;
    }
  });
  if (!module) {
    throw new Error(`Docusaurus was unable to resolve the "${moduleName}" ${moduleType}. Make sure one of the following packages are installed:
${modulePatterns.map((m) => `- ${m}`).join('\n')}`);
  }
  return module;
}

View on GitHub (pinned to 3f483e80e3)

Solutions

  1. Install the missing package: `npm install @docusaurus/preset-classic` (use the exact name from the error's candidate list).
  2. Fix typos in the preset/plugin string.
  3. For local plugins, pass the resolved path (`require.resolve('./my-plugin')`) instead of a package name.
  4. In a monorepo, ensure the package is built (`pnpm --filter <pkg> build`) and resolvable from the site dir.

Example fix

// before
presets: ['classic'],  // but @docusaurus/preset-classic not installed
// after (install first)
//   npm i @docusaurus/preset-classic
presets: ['classic'],
Defensive patterns

Strategy: validation

Validate before calling

function isResolvable(name: string): boolean {
  try { require.resolve(name); return true; } catch { return false; }
}
if (!isResolvable('@docusaurus/preset-classic')) {
  throw new Error('Run: npm i @docusaurus/preset-classic');
}

Try / catch

try {
  const preset = resolveModuleName('classic', 'preset');
} catch (e) {
  console.error('Preset not installed:', (e as Error).message);
  throw e;
}

Prevention

When it happens

Trigger: Referencing `presets: ['classic']`, `themes: ['live-codeblock']`, or `plugins: ['my-plugin']` when the corresponding npm package is not installed. The loop at moduleShorthand.ts:38-46 tries each pattern and the throw at :47-50 fires when `module` stays undefined.

Common situations: Forgetting to `npm install @docusaurus/preset-classic`; typo in the preset/plugin name; using a private/local plugin without the correct package name or path; monorepo package not built/linked.

Related errors


AI-assisted analysis of facebook/docusaurus@3f483e80e3 (2026-08-12). Data as JSON: /api/errors/eb29551813efb55a. Report an issue: GitHub.