withastro/astro · error · Error

[preview] No adapter found.

Error message

[preview] No adapter found.

What it means

Thrown by the preview command when the project requires server output (buildOutput !== 'static' or an adapter is otherwise expected) but no adapter is configured. Server-output previews delegate to the adapter's preview entrypoint, so without an adapter there is nothing to run.

Source

Thrown at packages/astro/src/core/preview/index.ts:63

	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 the
	// preview entrypoint of the integration package, relative to the user's project root.
	const require = createRequire(settings.config.root);
	const previewEntrypointUrl = pathToFileURL(
		require.resolve(settings.adapter.previewEntrypoint.toString()),
	).href;

	const previewModule = (await import(previewEntrypointUrl)) as Partial<PreviewModule>;
	if (typeof previewModule.default !== 'function') {
		throw new Error(`[preview] ${settings.adapter.name} cannot preview your app.`);

View on GitHub (pinned to d081033d5f)

Solutions

  1. Install and add an adapter: `npx astro add node` (or @astrojs/vercel, @astrojs/cloudflare, etc.).
  2. Ensure the adapter is listed under integrations or via the adapter config option in astro.config.
  3. If you intended a static preview, set output: 'static' or prerender routes so buildOutput becomes static.

Example fix

// before - astro.config.mjs has output: 'server', no adapter

// after
import node from '@astrojs/node';
export default defineConfig({ output: 'server', adapter: node({ mode: 'standalone' }) });
Defensive patterns

Strategy: validation

Validate before calling

// Ensure an adapter is configured for server output.
import { readFileSync } from 'node:fs';
const config = readFileSync('astro.config.mjs', 'utf8');
if (/output:\s*['"]server['"]/.test(config) && !/adapter\s*:/.test(config)) {
  throw new Error('Add an adapter: npx astro add node');
}

Type guard

function hasAdapter(settings: { adapter?: unknown }): boolean {
  return Boolean(settings.adapter);
}

Prevention

When it happens

Trigger: Running `astro preview` when settings.buildOutput is 'server' (any route is on-demand / prerender defaults to false) and settings.adapter is undefined. The check `if (!settings.adapter)` fires after the static branch.

Common situations: Setting output: 'server' (or prerender: false) without installing an adapter; removing the adapter integration from config but keeping server output; previewing an SSR project before `astro add node` (or another adapter).

Related errors


AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12). Data as JSON: /api/errors/24a5fe533a1d773f. Report an issue: GitHub.