facebook/docusaurus · error · Error

A Docusaurus plugin returned 'undefined', which is forbidden

Error message

A Docusaurus plugin returned 'undefined', which is forbidden.\nA plugin is expected to return an object having at least a 'name' property.\nIf you want a plugin to self-disable depending on context/options, you can explicitly return 'null' instead of 'undefined'

What it means

Thrown during plugin initialization when a plugin function returns `undefined`. Docusaurus requires plugins to return either a valid plugin object (with at least `name`) or explicitly `null` to self-disable. Returning `undefined` is almost always a bug — a missing `return` or an early branch that falls through. The check sits in plugins/init.ts:147-156.

Source

Thrown at packages/docusaurus/src/server/plugins/init.ts:152

    // Example: the theme classic plugin will read siteConfig.themeConfig
    context.siteConfig.themeConfig = {
      ...context.siteConfig.themeConfig,
      ...doValidateThemeConfig(normalizedPluginConfig),
    };

    const pluginInstance = await normalizedPluginConfig.plugin(
      context,
      pluginOptions,
    );

    // Returning null has been explicitly allowed
    // It's a way for plugins to self-disable depending on context
    // See https://github.com/facebook/docusaurus/pull/10286
    if (pluginInstance === null) {
      return {config: normalizedPluginConfig, plugin: null};
    }
    if (pluginInstance === undefined) {
      throw new Error(
        `A Docusaurus plugin returned 'undefined', which is forbidden.
A plugin is expected to return an object having at least a 'name' property.
If you want a plugin to self-disable depending on context/options, you can explicitly return 'null' instead of 'undefined'`,
      );
    }

    if (!pluginInstance?.name) {
      throw new Error(
        `A Docusaurus plugin is missing a 'name' property.
Note that even inline/anonymous plugin functions require a 'name' property.`,
      );
    }

    const plugin: InitializedPlugin = {
      ...pluginInstance,
      options: pluginOptions,
      version: pluginVersion,
      path: path.dirname(normalizedPluginConfig.entryPath),

View on GitHub (pinned to 3f483e80e3)

Solutions

  1. Ensure the plugin function returns an object with a `name` property on every code path.
  2. If the plugin should opt out in some context, `return null;` explicitly (this is the supported self-disable contract).
  3. Add a TypeScript return type (`function myPlugin(...): Plugin` / `Promise<Plugin | null>`) so the compiler catches missing returns.

Example fix

// before
function myPlugin() {
  if (skip) { return; } // returns undefined
  return { name: 'my-plugin' };
}
// after
function myPlugin() {
  if (skip) { return null; }
  return { name: 'my-plugin' };
}
Defensive patterns

Strategy: type-guard

Validate before calling

function assertPluginReturn(value: unknown) {
  if (value === undefined) throw new Error('Plugin returned undefined — return null to self-disable');
}

Type guard

function isValidPluginReturn<T>(v: T | undefined | null): v is T | null {
  return v !== undefined;
}

Prevention

When it happens

Trigger: A plugin function whose body has an execution path with no `return`; an arrow function with a block body that forgets `return`; an early `if` guard that returns nothing. `pluginInstance === undefined` at init.ts:151 triggers the throw.

Common situations: Authoring a custom plugin and forgetting the `return` statement; conditional plugin logic where one branch omits `return`; converting a function-expression to an arrow block without adding `return`.

Understand the failure class

Related errors


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