withastro/astro · error · Error
[preview] The output directory
Error message
[preview] The output directory ${outDirPath} does not exist. Did you run `astro build`? What it means
`astro preview` serves the artifacts produced by `astro build`. For a static build (no adapter preview entrypoint), it starts a static file server rooted at the client output directory (`dist/client` by default) and first verifies it exists with `fs.existsSync`. If the directory is absent there is nothing to serve, so preview aborts and suggests running the build first.
Solutions
- Run `astro build` before `astro preview` (e.g. chain them: `astro build && astro preview`)
- Verify `outDir` and `build.client` in astro.config match the directory preview expects
- Run preview from the project root (where astro.config lives) so the relative outDir resolves correctly
- If the build itself fails, fix the build errors first — preview cannot run without its output
Example fix
# before astro preview # after astro build && astro preview
Defensive patterns
Strategy: validation
Validate before calling
// scripts/preview.mjs — gate preview on the build output existing
import { existsSync } from 'node:fs';
import { resolve } from 'node:path';
const clientOutDir = resolve('dist/client'); // must match build.client / outDir
if (!existsSync(clientOutDir)) {
console.error(`Missing ${clientOutDir} — run \`astro build\` first`);
process.exit(1);
}
// then spawn `astro preview` Prevention
- Chain build and preview in one npm script: `"preview": "astro build && astro preview"`
- Keep `outDir`/`build.client` stable between builds and previews — re-run build after changing them
- Run preview from the project root so the relative output directory resolves correctly
- In CI, make the preview job depend on the build job or copy the dist artifact explicitly
When it happens
Trigger: Running `astro preview` on a static site before `astro build` has ever emitted output; a build that failed partway before writing the client bundle; a custom `outDir`/`build.client` config that differs from where the build actually wrote; running preview from the wrong working directory so the relative outDir resolves elsewhere.
Common situations: Fresh clone where only `astro dev` was run; CI pipelines that separate build and preview stages and skip the build step; `dist/` removed by a clean task or `.gitignore` workflow; outDir changed in astro.config after the last build.
Related errors
- [preview] No adapter found.
- [preview] The adapter does not support the preview command.
- Another astro dev server is already running. URL
- Another astro preview server is already running. URL
- Be sure to follow the
AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18).
Data as JSON: /api/errors/5f2addb23c15d07c.
Report an issue: GitHub.
Appendix: source
Thrown at packages/astro/src/core/preview/index.ts:54
const settings = await runHookConfigSetup({
settings: _settings,
command: 'preview',
logger: logger,
});
// Create a route manifest and determine buildOutput from actual routes.
// Route scanning sets settings.buildOutput to 'server' if any route is non-prerendered.
settings.buildOutput = getPrerenderDefault(settings.config) ? 'static' : 'server';
await createRoutesList({ settings: settings, cwd: inlineConfig.root }, logger);
await runHookConfigDone({ settings: settings, logger: logger, command: 'preview' });
if (settings.buildOutput === 'static' && !settings.adapter?.previewEntrypoint) {
const clientOutDir = getClientOutputDirectory(settings);
if (!fs.existsSync(clientOutDir)) {
const outDirPath = fileURLToPath(clientOutDir);
throw new Error(
`[preview] The output directory ${outDirPath} does not exist. Did you run \`astro build\`?`,
);
}
const server = await createStaticPreviewServer(settings, logger);
return server;
}
if (!settings.adapter) {
throw new Error(`[preview] No adapter found.`);
}
if (!settings.adapter.previewEntrypoint) {
throw new Error(
`[preview] The ${settings.adapter.name} adapter does not support the preview command.`,
);
}
// We need to use require.resolve() here so that advanced package managers like pnpm
// don't treat this as a dependency of Astro itself. This correctly resolves theView on GitHub (pinned to 52e6c34790)