withastro/astro · error · Error

[preview] ${settings.adapter.name} cannot preview your app.

Error message

[preview] ${settings.adapter.name} cannot preview your app.

What it means

Thrown by preview after dynamically importing the adapter's previewEntrypoint: the module's default export must be a function (the preview server factory). If previewModule.default is not a function, the adapter's preview entrypoint is malformed or incompatible, and preview cannot proceed.

Source

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

		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.`);
	}

	const server = await previewModule.default({
		outDir: settings.config.outDir,
		client: settings.config.build.client,
		server: settings.config.build.server,
		serverEntrypoint: new URL(settings.config.build.serverEntry, settings.config.build.server),
		host: getResolvedHostForHttpServer(settings.config.server.host),
		port: settings.config.server.port,
		base: settings.config.base,
		logger: new AstroIntegrationLogger(logger.options, settings.adapter.name),
		headers: settings.config.server.headers,
		allowedHosts: settings.config.server.allowedHosts,
		open: settings.config.server.open,
		root: settings.config.root,
	});

	return server;

View on GitHub (pinned to d081033d5f)

Solutions

  1. Upgrade the adapter and Astro together to compatible versions.
  2. Verify the adapter package is intact (reinstall node_modules / lockfile).
  3. Switch to an adapter known to ship a working preview entrypoint (e.g. @astrojs/node).
  4. If authoring an adapter, ensure the preview entrypoint's default export is an async function returning a PreviewServer.

Example fix

// before - astro and adapter versions mismatched
astro preview  // entrypoint default export not a function

// after
pnpm update astro @astrojs/node
astro build && astro preview
Defensive patterns

Strategy: type-guard

Validate before calling

// Validate the adapter's preview module shape before invoking.
const previewModule = await import(previewEntrypointUrl);
if (typeof previewModule.default !== 'function') {
  throw new Error('adapter preview entrypoint default export is not a function');
}
const server = await previewModule.default(opts);

Type guard

function isPreviewModule(m: unknown): m is { default: (opts: any) => Promise<PreviewServer> } {
  return typeof (m as any)?.default === 'function';
}

Try / catch

try {
  await previewModule.default(opts);
} catch (e) {
  if (e instanceof Error && /cannot preview/i.test(e.message)) {
    // adapter entrypoint malformed; reinstall/upgrade adapter
  }
  throw e;
}

Prevention

When it happens

Trigger: An adapter declares a previewEntrypoint but the resolved module's default export is missing, not a function, or is the wrong shape. The check `typeof previewModule.default !== 'function'` fails after the import.

Common situations: Adapter version mismatch where the preview entrypoint changed shape; a broken/partial adapter package; pointing previewEntrypoint at a non-default-export module; adapter/astro version skew after upgrading one but not the other.

Related errors


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