sveltejs/kit · error

Cannot save ${decoded} as ${parent} is already a file. See h

Error message

Cannot save ${decoded} as ${parent} is already a file. See https://svelte.dev/docs/kit/page-options#prerender-route-conflicts for more information

What it means

A prerendered route's output destination's parent directory already exists as a FILE. This happens when one route (e.g. `/foo`) saved a file named `foo` (or `foo.html`) and another route (e.g. `/foo/bar`) needs `foo` to be a directory. Both cannot coexist on disk.

Source

Thrown at packages/kit/src/core/postbuild/prerender.js:603

			} else {
				log.warn(`location header missing on redirect received from ${decoded}`);
			}

			return;
		}

		if (response.status === 200) {
			if (existsSync(dest) && statSync(dest).isDirectory()) {
				throw new Error(
					`Cannot save ${decoded} as it is already a directory. See https://svelte.dev/docs/kit/page-options#prerender-route-conflicts for more information`
				);
			}

			const dir = dirname(dest);

			if (existsSync(dir) && !statSync(dir).isDirectory()) {
				const parent = decoded.split('/').slice(0, -1).join('/');
				throw new Error(
					`Cannot save ${decoded} as ${parent} is already a file. See https://svelte.dev/docs/kit/page-options#prerender-route-conflicts for more information`
				);
			}

			mkdirSync(dir, { recursive: true });

			writeFileSync(dest, body);
			written.add(file);

			if (is_html) {
				prerendered.pages.set(decoded, {
					file
				});
			} else {
				prerendered.assets.set(decoded, {
					type
				});
			}

View on GitHub (pinned to 03f1687fe6)

Solutions

  1. Rename one of the conflicting routes so the file path and directory path differ
  2. Nest the file-producing route, e.g. move the file endpoint from `/foo` to `/foo/index` or `/files/foo`
  3. Adjust the dynamic route's generated slugs (exclude the colliding value) or use route groups to restructure paths
  4. See https://svelte.dev/docs/kit/page-options#prerender-route-conflicts

Example fix

// before
// src/routes/docs/+server.js   -> writes file 'docs'
// src/routes/docs/intro/+page.svelte -> needs directory 'docs/'

// after
// src/routes/files/[name]/+server.js  -> /files/docs serves the file
// src/routes/docs/intro/+page.svelte  -> docs/ stays a directory
Defensive patterns

Strategy: validation

Validate before calling

// ensure no route is both a file producer and a path prefix of another
const routes = ['/docs', '/docs/intro'];
for (const r of routes) {
  if (routes.some((o) => o !== r && o.startsWith(r + '/'))) {
    console.warn(`Route ${r} is a prefix of another; file/dir clash possible in prerender`);
  }
}

Try / catch

try {
  await prerender();
} catch (e) {
  if (String(e.message).includes('is already a file')) {
    console.error('A route output file collides with a nested route directory; rename one');
  }
  throw e;
}

Prevention

When it happens

Trigger: Routes `/foo` (saving file `foo.html`/`foo`) and `/foo/bar` prerendered in the same build; typically caused by a dynamic segment colliding with a sibling file-producing route.

Common situations: A `[slug]` route generating slug "bar" under `/foo` while a static file-producing route `/foo` exists; endpoints returning files (e.g. `/docs` returning a PDF) alongside nested pages `/docs/intro`.

Related errors


AI-assisted analysis of sveltejs/kit@03f1687fe6 (2026-09-02). Data as JSON: /api/errors/a966e654a464a32d. Report an issue: GitHub.