{"record":{"id":"48c0d9eff6bccdba","repo":"withastro/astro","slug":"the-server-entrypoint-doesn-t-have-a-handler-are","errorCode":null,"errorMessage":"The server entrypoint doesn't have a handler. Are you sure this is the right file?","messagePattern":"The server entrypoint doesn't have a handler\\. Are you sure this is the right file\\?","errorType":"exception","errorClass":"AstroError","httpStatus":null,"severity":"error","filePath":"packages/integrations/node/src/preview.ts","lineNumber":18,"sourceCode":"import { fileURLToPath } from 'node:url';\nimport type { CreatePreviewServer } from 'astro';\nimport { AstroError } from 'astro/errors';\nimport { logListeningOn } from './log-listening-on.js';\nimport { createServer } from './standalone.js';\n\ntype ServerModule = typeof import('./server.js');\ntype MaybeServerModule = Partial<ServerModule>;\n\nconst createPreviewServer: CreatePreviewServer = async (preview) => {\n\tlet ssrHandler: ServerModule['handler'];\n\ttry {\n\t\tprocess.env.ASTRO_NODE_AUTOSTART = 'disabled';\n\t\tconst ssrModule: MaybeServerModule = await import(preview.serverEntrypoint.toString());\n\t\tif (typeof ssrModule.handler === 'function') {\n\t\t\tssrHandler = ssrModule.handler;\n\t\t} else {\n\t\t\tthrow new AstroError(\n\t\t\t\t`The server entrypoint doesn't have a handler. Are you sure this is the right file?`,\n\t\t\t);\n\t\t}\n\t} catch (err) {\n\t\tif (\n\t\t\t(err as any).code === 'ERR_MODULE_NOT_FOUND' &&\n\t\t\t(err as any).url === preview.serverEntrypoint.href\n\t\t) {\n\t\t\tthrow new AstroError(\n\t\t\t\t`The server entrypoint ${fileURLToPath(\n\t\t\t\t\tpreview.serverEntrypoint,\n\t\t\t\t)} does not exist. Have you ran a build yet?`,\n\t\t\t);\n\t\t} else {\n\t\t\tthrow err;\n\t\t}\n\t}\n\t// If the user didn't specify a host, it will already have been defaulted to","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/withastro/astro/blob/52e6c34790cc8ac4e69e6135ace06049867e5c4a/packages/integrations/node/src/preview.ts#L1-L36","documentation":"astro preview with the Node adapter dynamically imports the built SSR entry (preview.serverEntrypoint, normally dist/server/entry.mjs) and requires a named handler export that the adapter's server build produces. If the module imports fine but handler is not a function, preview refuses to start because it has nothing to serve requests with.","triggerScenarios":"The server entry was overwritten or replaced (custom build step, post-processing script) so it default-exports instead of exporting handler; previewing an outDir built by a different setup; a stale or partially overwritten dist where the entry no longer matches the adapter's expected shape.","commonSituations":"Custom bundling/patching of dist/server/entry.mjs; switching adapters or output modes without cleaning dist; entry templates that export app instead of handler.","solutions":["Delete dist/ and re-run astro build with the Node adapter configured (output: 'server') so the real entry with a named handler is regenerated","If you use a custom server entry, export the handler: export const handler = (req, res) => app(req, res)","Verify preview.serverEntrypoint / outDir were not redirected to a non-adapter file"],"exampleFix":"// before (custom entry)\nexport default app;\n// after\nexport const handler = (req, res) => app(req, res);","handlingStrategy":"validation","validationCode":"import { pathToFileURL } from 'node:url';\nconst entry = 'dist/server/entry.mjs';\nconst mod: any = await import(pathToFileURL(entry).href);\nif (typeof mod.handler !== 'function') {\n  throw new Error(`${entry} has no handler export; rebuild with the node adapter`);\n}","typeGuard":"type ServerModule = { handler: (req: IncomingMessage, res: ServerResponse) => void | Promise<void> };\nfunction isServerModule(mod: unknown): mod is ServerModule {\n  return typeof (mod as any)?.handler === 'function';\n}","tryCatchPattern":null,"preventionTips":["Run astro build immediately before astro preview in the same environment","Clean dist/ whenever you change adapters or output settings","If post-processing the entry, re-add a named handler export"],"tags":["node","preview","build-output","entrypoint"],"backgroundTag":"missing-entrypoint-export","analyzedSha":"52e6c34790cc8ac4e69e6135ace06049867e5c4a","analyzedAt":"2026-08-18T18:48:03.901Z","contentChangedAt":"2026-08-18T18:48:03.901Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}