facebook/docusaurus · error · ReactContextError

Hook is called outside the <DocsPreferredVersionContextProvi

Error message

Hook is called outside the <DocsPreferredVersionContextProvider>. 

What it means

Thrown by useDocsPreferredVersionContext() when the context value is falsy, i.e. no <DocsPreferredVersionContextProvider> ancestor. This provider (the safe wrapper DocsPreferredVersionContextProvider around the unsafe variant) persists the user's last-visited version per plugin id. ReactContextError yields 'Hook useDocsPreferredVersionContext is called outside the <DocsPreferredVersionContextProvider>.'. Note the guard here is `if (!value)` rather than a sentinel.

Source

Thrown at packages/docusaurus-plugin-content-docs/src/client/docsPreferredVersion.tsx:187

 * This is a maybe-layer. If the docs plugin is not enabled, this provider is a
 * simple pass-through.
 */
export function DocsPreferredVersionContextProvider({
  children,
}: {
  children: ReactNode;
}): ReactNode {
  return (
    <DocsPreferredVersionContextProviderUnsafe>
      {children}
    </DocsPreferredVersionContextProviderUnsafe>
  );
}

function useDocsPreferredVersionContext(): ContextValue {
  const value = useContext(Context);
  if (!value) {
    throw new ReactContextError('DocsPreferredVersionContextProvider');
  }
  return value;
}

/**
 * Returns a read-write interface to a plugin's preferred version. The
 * "preferred version" is defined as the last version that the user visited.
 * For example, if a user is using v3, even when v4 is later published, the user
 * would still be browsing v3 docs when she opens the website next time. Note,
 * the `preferredVersion` attribute will always be `null` before mount.
 */
export function useDocsPreferredVersion(
  pluginId: string | undefined = DEFAULT_PLUGIN_ID,
): {
  preferredVersion: GlobalVersion | null;
  savePreferredVersionName: (versionName: string) => void;
} {
  const docsData = useDocsData(pluginId);

View on GitHub (pinned to 3f483e80e3)

Solutions

  1. Ensure <DocsPreferredVersionContextProvider> remains in the root layout (Docusaurus wires it via the theme's providers; keep it when swizzling Root).
  2. Only call useDocsPreferredVersion() under that provider subtree.
  3. In tests, wrap renders in DocsPreferredVersionContextProvider.
  4. If the component is used outside versioned contexts, gate the call behind a route/version check.

Example fix

// before: swizzled Root dropped the provider
const Root = ({children}) => <>{children}</>;
// after: keep the provider in the provider chain
const Root = ({children}) => (
  <DocsPreferredVersionContextProvider>
    {children}
  </DocsPreferredVersionContextProvider>
);
Defensive patterns

Strategy: validation

Validate before calling

import {useContext} from 'react';
import {DocsPreferredVersionContext} from '@docusaurus/plugin-content-docs/client';

function useHasPreferredVersionProvider() {
  return useContext(DocsPreferredVersionContext) != null;
}
// (export the context or use the provider's presence structurally)

Prevention

When it happens

Trigger: Calling useDocsPreferredVersion() outside the provider tree; swizzling the root layout and dropping DocsPreferredVersionContextProvider; rendering a version-aware component on a page not under the provider.

Common situations: Customizing the root Theme/Layout and removing the provider that Docusaurus wires into it; reusing a version-switcher component in a context where the provider was never mounted; partial swizzle that kept the unsafe provider but removed the safe wrapper.

Related errors


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