{"record":{"id":"8e0cbddd03bba46a","repo":"withastro/astro","slug":"astrojs-node-could-not-find-the-server-director","errorCode":null,"errorMessage":"[@astrojs/node] Could not find the server directory \"${serverFolder}\" by walking up from \"${import.meta.url}\". This can happen when the server entry point is bundled into a single file (e.g. with esbuild) so that import.meta.url no longer contains the original \"${serverFolder}\" path segment. When bundling the server entry, make sure the output path contains a \"${serverFolder}\" directory segment, or avoid bundling the server entry entirely.","messagePattern":"\\[@astrojs/node\\] Could not find the server directory \"(.+?)\" by walking up from \"(.+?)\"\\. This can happen when the server entry point is bundled into a single file \\(e\\.g\\. with esbuild\\) so that import\\.meta\\.url no longer contains the original \"(.+?)\" path segment\\. When bundling the server entry, make sure the output path contains a \"(.+?)\" directory segment, or avoid bundling the server entry entirely\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/integrations/node/src/shared.ts","lineNumber":37,"sourceCode":"export function resolveClientDir(options: Options) {\n\t// options.client and options.server are file:// URLs set at build time\n\t// e.g., \"file:///project/dist/client/\" and \"file:///project/dist/server/\"\n\tconst clientURLRaw = new URL(options.client);\n\tconst serverURLRaw = new URL(options.server);\n\n\t// Calculate relative path from server to client (e.g., \"../client\")\n\t// This relative path is stable regardless of where the build output is deployed\n\tconst rel = path.relative(url.fileURLToPath(serverURLRaw), url.fileURLToPath(clientURLRaw));\n\n\t// Find the server entry folder by walking up from this file's location\n\t// We need to find the actual runtime location, not the build-time paths\n\tconst serverFolder = path.basename(options.server);\n\tlet serverEntryFolderURL = path.dirname(import.meta.url);\n\tlet previous = '';\n\twhile (!serverEntryFolderURL.endsWith(serverFolder)) {\n\t\t// Guard against infinite loop\n\t\tif (serverEntryFolderURL === previous) {\n\t\t\tthrow new Error(\n\t\t\t\t`[@astrojs/node] Could not find the server directory \"${serverFolder}\" ` +\n\t\t\t\t\t`by walking up from \"${import.meta.url}\". This can happen when the server ` +\n\t\t\t\t\t`entry point is bundled into a single file (e.g. with esbuild) so that ` +\n\t\t\t\t\t`import.meta.url no longer contains the original \"${serverFolder}\" path segment. ` +\n\t\t\t\t\t`When bundling the server entry, make sure the output path contains a ` +\n\t\t\t\t\t`\"${serverFolder}\" directory segment, or avoid bundling the server entry entirely.`,\n\t\t\t);\n\t\t}\n\t\tprevious = serverEntryFolderURL;\n\t\tserverEntryFolderURL = path.dirname(serverEntryFolderURL);\n\t}\n\n\t// Resolve the client directory by applying the relative path to the runtime server location\n\tconst serverEntryURL = serverEntryFolderURL + '/entry.mjs';\n\tconst clientURL = new URL(appendForwardSlash(rel), serverEntryURL);\n\treturn url.fileURLToPath(clientURL);\n}\n","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/withastro/astro/blob/52e6c34790cc8ac4e69e6135ace06049867e5c4a/packages/integrations/node/src/shared.ts#L19-L55","documentation":"At runtime the Node adapter walks up from import.meta.url (shared.ts) until it finds a directory whose name equals basename(options.server) (the build.server folder, default 'server'); it uses that anchor to compute the relative path from the server bundle to the client assets. If the server entry was re-bundled into a file whose path no longer contains that segment, the walk reaches the filesystem root and throws with this explanation.","triggerScenarios":"Post-processing dist/server/entry.mjs with esbuild/webpack/pkg/etc. so the output lands outside a directory named 'server'; copying the bundled entry to another location before running it; renaming build.server without keeping the matching segment in the deployed output path.","commonSituations":"Deploy pipelines that bundle the server output into a single file at a path like dist/bundle.mjs; Docker images that flatten the build output; custom esbuild steps inherited from other adapters.","solutions":["Emit the bundle inside the server folder so the path keeps the segment, e.g. dist/server/bundle.mjs","Avoid re-bundling the server entry entirely and run dist/server/entry.mjs as built","If you rename the folder, keep a path segment matching basename(config.build.server) in the final output location"],"exampleFix":"# before\nesbuild dist/server/entry.mjs --bundle --outfile=dist/bundle.mjs\n# after\nesbuild dist/server/entry.mjs --bundle --outfile=dist/server/bundle.mjs","handlingStrategy":"validation","validationCode":"import path from 'node:path';\nconst serverFolder = path.basename(new URL(config.build.server).pathname); // default 'server'\nconst outSegments = path.resolve(outfile).split(path.sep);\nif (!outSegments.includes(serverFolder)) {\n  throw new Error(`bundle output must keep a '${serverFolder}' path segment`);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Emit bundled server output inside dist/server/ so the segment survives","Smoke-test the bundled entry locally with node before deploying","If renaming build.server, mirror the rename in the bundler output path"],"tags":["node","bundling","deployment","import-meta-url"],"backgroundTag":"bundler-path-resolution","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"}