{"record":{"id":"c13e1e0331b730c7","repo":"withastro/astro","slug":"no-files-found-to-copy","errorCode":null,"errorMessage":"No files found to copy","messagePattern":"No files found to copy","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/internal-helpers/src/fs.ts","lineNumber":51,"sourceCode":"\n/**\n * Copies files into a folder keeping the folder structure intact.\n * The resulting file tree will start at the common ancestor.\n *\n * @param {URL[]} files A list of files to copy (absolute path).\n * @param {URL} outDir Destination folder where to copy the files to (absolute path).\n * @param {URL[]} [exclude] A list of files to exclude (absolute path).\n * @returns {Promise<string>} The common ancestor of the copied files.\n */\nexport async function copyFilesToFolder(\n\tfiles: URL[],\n\toutDir: URL,\n\texclude: URL[] = [],\n): Promise<string> {\n\tconst excludeList = exclude.map((url) => fileURLToPath(url));\n\tconst fileList = files.map((url) => fileURLToPath(url)).filter((f) => !excludeList.includes(f));\n\n\tif (files.length === 0) throw new Error('No files found to copy');\n\n\tlet commonAncestor = nodePath.dirname(fileList[0]);\n\tfor (const file of fileList.slice(1)) {\n\t\twhile (!file.startsWith(commonAncestor)) {\n\t\t\tcommonAncestor = nodePath.dirname(commonAncestor);\n\t\t}\n\t}\n\n\tfor (const origin of fileList) {\n\t\tconst dest = new URL(nodePath.relative(commonAncestor, origin), outDir);\n\n\t\tconst realpath = await fs.realpath(origin);\n\t\tconst isSymlink = realpath !== origin;\n\t\tconst isDir = (await fs.stat(origin)).isDirectory();\n\n\t\t// Create directories recursively\n\t\tif (isDir && !isSymlink) {\n\t\t\tawait fs.mkdir(new URL('..', dest), { recursive: true });","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/withastro/astro/blob/52e6c34790cc8ac4e69e6135ace06049867e5c4a/packages/internal-helpers/src/fs.ts#L33-L69","documentation":"`copyFilesToFolder` in @astrojs/internal-helpers copies a list of traced files into a build output folder and throws immediately when the input array is empty — there is nothing to copy and no common ancestor to compute. In practice it is called by the Netlify and Vercel adapters' Node file-trace step (`lib/nft.ts`) to copy files that the server bundle references at runtime.","triggerScenarios":"File tracing (via @vercel/nft) returns an empty set — e.g. the server entry produced no external file dependencies, or the tracing glob/copy step was fed an empty list during an adapter build. Direct callers hit it by passing an empty array, typically the result of a glob that matched nothing.","commonSituations":"Building with the Netlify/Vercel adapter where everything is bundled and no external files need copying; adapter version mismatches after upgrading Astro; scripts using this helper with a filtered file list that ends up empty. (Note: the guard checks `files.length`, not the post-exclusion list, so excluding every file produces a different downstream failure, not this error.)","solutions":["If calling the helper directly: check `files.length > 0` before invoking and skip the copy when empty","On adapter builds: update @astrojs/vercel / @astrojs/netlify to the latest version compatible with your Astro version","Verify the server entry was actually built (the build log should show SSR output) before the trace step"],"exampleFix":"// before\nawait copyFilesToFolder(files, outDir);\n\n// after\nif (files.length > 0) {\n  await copyFilesToFolder(files, outDir);\n}","handlingStrategy":"validation","validationCode":"if (files.length === 0) {\n  console.warn('No traced files to copy; skipping copy step');\n} else {\n  await copyFilesToFolder(files, outDir);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check list length before calling copy APIs that require non-empty input","Keep adapter and Astro versions in lockstep so the trace step receives the files it expects"],"tags":["build","adapter","file-trace","fs"],"backgroundTag":"empty-input-list","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"}