withastro/astro · error · Error

No files found to copy

Error message

No files found to copy

What it means

`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.

Solutions

  1. If calling the helper directly: check `files.length > 0` before invoking and skip the copy when empty
  2. On adapter builds: update @astrojs/vercel / @astrojs/netlify to the latest version compatible with your Astro version
  3. Verify the server entry was actually built (the build log should show SSR output) before the trace step

Example fix

// before
await copyFilesToFolder(files, outDir);

// after
if (files.length > 0) {
  await copyFilesToFolder(files, outDir);
}
Defensive patterns

Strategy: validation

Validate before calling

if (files.length === 0) {
  console.warn('No traced files to copy; skipping copy step');
} else {
  await copyFilesToFolder(files, outDir);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.)

Related errors


AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18). Data as JSON: /api/errors/c13e1e0331b730c7. Report an issue: GitHub.

Appendix: source

Thrown at packages/internal-helpers/src/fs.ts:51

/**
 * Copies files into a folder keeping the folder structure intact.
 * The resulting file tree will start at the common ancestor.
 *
 * @param {URL[]} files A list of files to copy (absolute path).
 * @param {URL} outDir Destination folder where to copy the files to (absolute path).
 * @param {URL[]} [exclude] A list of files to exclude (absolute path).
 * @returns {Promise<string>} The common ancestor of the copied files.
 */
export async function copyFilesToFolder(
	files: URL[],
	outDir: URL,
	exclude: URL[] = [],
): Promise<string> {
	const excludeList = exclude.map((url) => fileURLToPath(url));
	const fileList = files.map((url) => fileURLToPath(url)).filter((f) => !excludeList.includes(f));

	if (files.length === 0) throw new Error('No files found to copy');

	let commonAncestor = nodePath.dirname(fileList[0]);
	for (const file of fileList.slice(1)) {
		while (!file.startsWith(commonAncestor)) {
			commonAncestor = nodePath.dirname(commonAncestor);
		}
	}

	for (const origin of fileList) {
		const dest = new URL(nodePath.relative(commonAncestor, origin), outDir);

		const realpath = await fs.realpath(origin);
		const isSymlink = realpath !== origin;
		const isDir = (await fs.stat(origin)).isDirectory();

		// Create directories recursively
		if (isDir && !isSymlink) {
			await fs.mkdir(new URL('..', dest), { recursive: true });

View on GitHub (pinned to 52e6c34790)