facebook/docusaurus · error

Expected output HTML file to be found at ${withTrailingSlash

Error message

Expected output HTML file to be found at ${withTrailingSlashPath} for permalink ${permalink}.

What it means

Thrown by readOutputHTMLFile() when neither the trailing-slash variant (permalink/index.html) nor the non-trailing-slash variant (permalink.html) exists in the output directory. The function computes both candidate paths based on the trailingSlash config, probes each with fs.pathExists, and only throws if both are missing. The JSDoc marks this as an internal invariant: it 'should never happen as it would lead to a 404.'

Source

Thrown at packages/docusaurus-utils/src/emitUtils.ts:100

  outDir: string,
  trailingSlash: boolean | undefined,
): Promise<Buffer> {
  const withTrailingSlashPath = path.join(outDir, permalink, 'index.html');
  const withoutTrailingSlashPath = (() => {
    const basePath = path.join(outDir, permalink.replace(/\/$/, ''));
    const htmlSuffix = /\.html?$/i.test(basePath) ? '' : '.html';
    return `${basePath}${htmlSuffix}`;
  })();

  const possibleHtmlPaths = [
    trailingSlash !== false && withTrailingSlashPath,
    trailingSlash !== true && withoutTrailingSlashPath,
  ].filter((p): p is string => Boolean(p));

  const HTMLPath = await findAsyncSequential(possibleHtmlPaths, fs.pathExists);

  if (!HTMLPath) {
    throw new Error(
      `Expected output HTML file to be found at ${withTrailingSlashPath} for permalink ${permalink}.`,
    );
  }
  return fs.readFile(HTMLPath);
}

View on GitHub (pinned to 3f483e80e3)

Solutions

  1. Clear the build output directory (remove the build/ or out/ folder) and rebuild from scratch — this is by far the most common cause if the error appears after a trailingSlash or permalink config change.
  2. Inspect the permalink in the error; confirm the plugin that owns that route actually emits a static HTML file (plugins returning client-only routes with no SSR cannot be read this way).
  3. Verify trailingSlash in docusaurus.config.js is set consistently — the candidate paths depend on its value, so a mismatch with previously built output triggers the error.
  4. If you author a custom plugin, ensure addRoute() permalinks correspond to pages that produce index.html or permalink.html in the output.

Example fix

// before — stale build output after trailingSlash change
// run: rm -rf build && pnpm build

// after — clean rebuild resolves the candidate path mismatch
Defensive patterns

Strategy: try-catch

Validate before calling

import fs from 'fs-extra';
import path from 'path';

async function outputHtmlExists(outDir: string, permalink: string, trailingSlash?: boolean): Promise<boolean> {
  const candidates = [
    trailingSlash !== false && path.join(outDir, permalink, 'index.html'),
    trailingSlash !== true && `${path.join(outDir, permalink.replace(/\/$/, ''))}.html`,
  ].filter(Boolean) as string[];
  return (await Promise.all(candidates.map(p => fs.pathExists(p)))).some(Boolean);
}

if (!(await outputHtmlExists(outDir, permalink, trailingSlash))) {
  throw new Error(`No built HTML for ${permalink}; rebuild from a clean outDir.`);
}

Try / catch

try {
  await readOutputHTMLFile(permalink, outDir, trailingSlash);
} catch (err) {
  if (err instanceof Error && err.message.startsWith('Expected output HTML file')) {
    // this is an internal invariant; clear outDir and rebuild
  }
  throw err;
}

Prevention

When it happens

Trigger: An internal Docusaurus caller (e.g. the sitemap or SSR post-processing pass) asks for the rendered HTML of a permalink whose build output file was never written or was written to an unexpected path. This usually points to a mismatch between the permalink a plugin registered and the file the bundler actually emitted.

Common situations: A custom plugin generates a permalink route but its corresponding static HTML file is not emitted (e.g. the route is client-only with no SSR). A trailingSlash configuration change where stale output from a previous build lingers in the outDir. Slugs with unexpected characters that get encoded differently between the permalink registry and the filesystem.

Related errors


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