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
- 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.
- 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).
- 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.
- 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
- Always build into a clean output directory (delete build/ first), especially after changing trailingSlash or permalink config.
- Ensure custom plugin routes emit a static HTML file (avoid pure client-only routes that need SSR read-back).
- Keep trailingSlash consistent across builds to avoid stale-path mismatches.
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
- You are trying to create client-side redirections to invalid
- Unable to get broken links for page ${pagePath}.
- Docusaurus Bug: server bundle export from "${filename}" must
- HTML minification failed (Terser)
- HTML minification failed (SWC)
AI-assisted analysis of facebook/docusaurus@3f483e80e3 (2026-08-12).
Data as JSON: /api/errors/eb377dfa2bf98f98.
Report an issue: GitHub.