facebook/docusaurus · critical · Error

The page component at ${path} doesn't have a default export.

Error message

The page component at ${path} doesn't have a default export. This makes it impossible to render anything. Consider default-exporting a React component.

What it means

ComponentCreator renders each route by reading the default export of the loaded module (loadedModule.default). If default is falsy it throws 'The page component at ${path} doesn't have a default export', because there is nothing to render. This almost always means the page file lacks `export default` or the route's __comp points at a module that is not a React component.

Source

Thrown at packages/docusaurus/src/client/exports/ComponentCreator.tsx:92

      // restore the chunk names' previous shape from this flat record.
      // We do so by taking advantage of the existing `chunkNames` and replacing
      // each chunk name with its loaded module, so we don't create another
      // object from scratch.
      const loadedModules = JSON.parse(JSON.stringify(chunkNames)) as {
        __comp?: React.ComponentType<object>;
        __context?: RouteContext;
        __props?: {[propName: string]: unknown};
        [attributeName: string]: unknown;
      };
      Object.entries(loaded).forEach(([keyPath, loadedModule]) => {
        // JSON modules are also loaded as `{ default: ... }` (`import()`
        // semantics) but we just want to pass the actual value to props.
        const chunk = loadedModule.default;
        // One loaded chunk can only be one of two things: a module (props) or a
        // component. Modules are always JSON, so `default` always exists. This
        // could only happen with a user-defined component.
        if (!chunk) {
          throw new Error(
            `The page component at ${path} doesn't have a default export. This makes it impossible to render anything. Consider default-exporting a React component.`,
          );
        }
        // A module can be a primitive, for example, if the user stored a string
        // as a prop. However, there seems to be a bug with swc-loader's CJS
        // logic, in that it would load a JSON module with content "foo" as
        // `{ default: "foo", 0: "f", 1: "o", 2: "o" }`. Just to be safe, we
        // first make sure that the chunk is non-primitive.
        if (typeof chunk === 'object' || typeof chunk === 'function') {
          Object.keys(loadedModule)
            .filter((k) => k !== 'default')
            .forEach((nonDefaultKey) => {
              (chunk as {[key: string]: unknown})[nonDefaultKey] =
                loadedModule[nonDefaultKey];
            });
        }
        // We now have this chunk prepared. Go down the key path and replace the
        // chunk name with the actual chunk.

View on GitHub (pinned to 3f483e80e3)

Solutions

  1. Open the file at the reported path and add `export default YourComponent`.
  2. If the module re-exports, add `export { default } from './Page'` or `export { Foo as default }`.
  3. Verify the route config (addRoute/plugin) points __comp at a component module, not a data/util module.
  4. Run `docusaurus clear` to drop stale build cache, then rebuild.

Example fix

// before (src/pages/help.tsx)
export function Help() {
  return <h1>Help</h1>;
}
// after
export default function Help() {
  return <h1>Help</h1>;
}
Defensive patterns

Strategy: validation

Validate before calling

import assert from 'node:assert';

async function checkPageDefaultExport(path: string) {
  const mod = await import(path);
  assert.ok(
    mod.default,
    `Page at ${path} has no default export; cannot render`,
  );
}

Type guard

const hasDefaultExport = <T>(
  mod: T,
): mod is T & {default: React.ComponentType} =>
  Boolean((mod as {default?: unknown}).default);

Prevention

When it happens

Trigger: A file in src/pages/ with only named exports; a plugin route whose component module has no default export; a re-export file like `export {Foo}` without `export default`; the route config __comp string resolving to a JSON/util module.

Common situations: Forgetting `export default` on a new page; using `export function Page()` and never adding the default; broken index/barrel re-export; HOC/memo wrapping that returns undefined; build caching an old version of a freshly edited page (run `docusaurus clear`).

Related errors


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