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
- Rename one of the conflicting routes so the file path and directory path differ
- Nest the file-producing route, e.g. move the file endpoint from `/foo` to `/foo/index` or `/files/foo`
- Adjust the dynamic route's generated slugs (exclude the colliding value) or use route groups to restructure paths
- 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
- Avoid routes that both return files and have child pages
- Put downloadable files under a dedicated prefix like /files/
- Constrain dynamic slugs to exclude values that collide with static siblings
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
- Cannot save ${decoded} as it is already a directory. See htt
- Could not find prerendered page ${file} for route ${path}
- Cannot access cloudflare:workers in a prerenderable route
- Could not find entry point
- ${relative} does not exist
AI-assisted analysis of sveltejs/kit@03f1687fe6 (2026-09-02).
Data as JSON: /api/errors/a966e654a464a32d.
Report an issue: GitHub.