sveltejs/kit · error · Error
Cloudflare Pages' _routes.json should be configured from the
Error message
Cloudflare Pages' _routes.json should be configured from the adapter option of the SvelteKit plugin in your vite.config.js. See https://svelte.dev/docs/kit/adapter-cloudflare#Options-routes
What it means
adapter-cloudflare generates _routes.json itself from the adapter's `routes` option. A hand-written _routes.json in the project root or in the assets directory conflicts with that generation and can silently break routing, so adapt() throws and points you at the SvelteKit plugin configuration instead.
Source
Thrown at packages/adapter-cloudflare/index.js:33
} from './utils.js';
import { exactRegex } from '@rolldown/pluginutils';
import { getRequest } from '@sveltejs/kit/node';
const name = '@sveltejs/adapter-cloudflare';
/** @type {typeof import('./index.js').default} */
export default function (options = {}) {
// Add a random query so we can reliably string-replace the stub
const stub_import =
import.meta.resolve('./src/virtual-cloudflare-workers.js') + '?' + crypto.randomUUID();
return {
name,
async adapt(builder) {
if (
fs.existsSync('_routes.json') ||
fs.existsSync(`${builder.config.files.assets}/_routes.json`)
) {
throw new Error(
"Cloudflare Pages' _routes.json should be configured from the adapter option of the SvelteKit plugin in your vite.config.js. See https://svelte.dev/docs/kit/adapter-cloudflare#Options-routes"
);
}
if (fs.existsSync(`${builder.config.files.assets}/_headers`)) {
throw new Error(
`The _headers file should be placed in the project root rather than the ${builder.config.files.assets} directory`
);
}
if (fs.existsSync(`${builder.config.files.assets}/_redirects`)) {
throw new Error(
`The _redirects file should be placed in the project root rather than the ${builder.config.files.assets} directory`
);
}
const { wrangler_config, building_for_cloudflare_pages } = validate_wrangler_config(
options.configView on GitHub (pinned to 03f1687fe6)
Solutions
- Delete the hand-written _routes.json from the project root and/or your static/assets directory.
- Configure routing via the adapter option instead, e.g. adapter({ routes: { include: ['/*'], exclude: ['/static/*'] } }).
- Re-run `vite build` so the adapter generates _routes.json from your option.
Example fix
// vite.config.js before
adapter({ routes: { include: ['/*'], exclude: ['<all>'] } });
// and delete: static/_routes.json
// after
adapter({ routes: { include: ['/*'], exclude: ['/img/*', '/fonts/*'] } }); Defensive patterns
Strategy: validation
Validate before calling
import fs from 'node:fs';
if (fs.existsSync('_routes.json') || fs.existsSync('static/_routes.json')) {
throw new Error('Remove hand-written _routes.json; configure the adapter routes option instead');
} Try / catch
try {
await viteBuild();
} catch (err) {
if (/_routes.json should be configured from the adapter option/.test(err.message)) {
console.error('Delete _routes.json and move routing rules into the adapter routes option');
}
throw err;
} Prevention
- Never commit _routes.json into the repo root or static/.
- Express routing intent via the adapter's routes option in vite.config.js.
- When migrating from plain Cloudflare Pages, remove legacy Pages config files first.
When it happens
Trigger: A _routes.json file exists in the project root or inside the configured assets directory (default `static/`) when running `vite build` with the Cloudflare adapter.
Common situations: Migrating a plain Cloudflare Pages project to SvelteKit and keeping the old _routes.json; copying Cloudflare docs examples that place _routes.json in static/.
Related errors
- Could not detect a supported production environment. See htt
- ${message}. Since you're using @sveltejs/adapter-auto, Svelt
- adapter-bun requires running the SvelteKit build with Bun. U
- ${log.message ?? String(log)}
- You should change envPrefix (${env_prefix}) to avoid conflic
AI-assisted analysis of sveltejs/kit@03f1687fe6 (2026-09-02).
Data as JSON: /api/errors/58c23d6c788a9ade.
Report an issue: GitHub.