withastro/astro · error · Error
[preview] cannot preview your app.
Error message
[preview] ${settings.adapter.name} cannot preview your app. What it means
Preview resolves the adapter's `previewEntrypoint` with `require.resolve()` relative to the project root (so package managers like pnpm do not hoist it into Astro), imports it as a module, and calls its default export to obtain the server. If that module's default export is anything other than a function, the adapter contract is broken — usually a malformed custom adapter, a broken package publish, or a version mismatch — and preview aborts.
Solutions
- Reinstall dependencies (`rm -rf node_modules && npm install` or `pnpm install`) to rule out a corrupted package
- Upgrade the adapter to a version compatible with your Astro version
- If you maintain the adapter, make the preview entrypoint export a default async function receiving the preview options and returning a server object
- Check the adapter package's `exports` map actually points `previewEntrypoint` at the file you think it does
Example fix
// before — adapter preview entrypoint
export const preview = async (options) => { /* start server */ };
// after
export default async function preview(options) {
const server = http.createServer(/* serve files from options.server outDir */);
await new Promise((r) => server.listen(options.port, options.host, r));
return { server, closed: false };
} Defensive patterns
Strategy: type-guard
Validate before calling
// adapter smoke test — import the preview entrypoint the way preview does
import { pathToFileURL } from 'node:url';
import { createRequire } from 'node:module';
const req = createRequire(process.cwd() + '/');
const mod = await import(pathToFileURL(req.resolve('./my-adapter/preview.js')).href);
if (typeof mod.default !== 'function') throw new Error('adapter preview entrypoint malformed'); Type guard
// Narrow an imported adapter preview module to a callable server factory
export function isPreviewModule(m: unknown): m is { default: (opts: any) => Promise<any> } {
return typeof (m as any)?.default === 'function';
} Prevention
- Pin adapter versions compatible with your Astro version (check peerDependencies)
- When authoring adapters, export `default async function preview(options)` returning `{ server, closed }`
- Reinstall node_modules after interrupted installs before debugging adapter load failures
When it happens
Trigger: A custom adapter whose preview entrypoint uses a named export (`export const preview`) or an object instead of `export default`; a partially published or corrupted adapter package where the entrypoint resolves to the wrong file (exports-map mismatch); an adapter version whose preview API predates the current Astro runtime.
Common situations: Authoring a first-party adapter and forgetting the default-export convention; mixing an adapter built for an older Astro with a newer core; a bad install (half-written files) after an interrupted npm/pnpm install.
Related errors
- [preview] No adapter found.
- [preview] The adapter does not support the preview command.
- The adapter uses `entrypointResolution: "explicit"` by…
- The server entrypoint doesn't have a handler. Are you sure…
- The server entrypoint
AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18).
Data as JSON: /api/errors/395ef1ed35e9b35e.
Report an issue: GitHub.
Appendix: 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 52e6c34790)