sveltejs/kit · error
Cannot prerender a root +server.js that returns a non-HTML r
Error message
Cannot prerender a root +server.js that returns a non-HTML response - static hosts always serve an HTML file for `${config.paths.base || '/'}` What it means
With full prerendering (e.g. adapter-static), the site root must be an HTML page. If your root +server.js handles GET at the base path and returns non-HTML (like JSON), the prerenderer refuses: static hosts map the root path to an HTML file (index.html), so a non-HTML root response cannot be represented on disk.
Source
Thrown at packages/kit/src/core/postbuild/prerender.js:538
/**
* @param {'pages' | 'dependencies' | 'data'} category
* @param {Response} response
* @param {string | Uint8Array} body
* @param {string} decoded
* @param {string} encoded
* @param {string | null} referrer
* @param {'linked' | 'fetched'} referenceType
*/
function save(category, response, body, decoded, encoded, referrer, referenceType) {
const response_type = Math.floor(response.status / 100);
const headers = Object.fromEntries(response.headers);
const type = headers['content-type'];
const is_html = response_type === REDIRECT || matches_content_type(type, 'text/html');
if (!is_html && response.status === 200 && decoded.slice(config.paths.base.length + 1) === '') {
throw new Error(
`Cannot prerender a root +server.js that returns a non-HTML response - static hosts always serve an HTML file for \`${config.paths.base || '/'}\``
);
}
const file = output_filename(decoded, is_html);
const dest = `${config.outDir}/output/prerendered/${category}/${file}`;
if (written.has(file)) return;
const encoded_route_id = response.headers.get('x-sveltekit-routeid');
const route_id = encoded_route_id != null ? decode_uri(encoded_route_id) : null;
if (route_id !== null) prerendered_routes.add(route_id);
if (response_type === REDIRECT) {
const location = headers['location'];
if (location) {
const resolved = resolve(encoded, location);View on GitHub (pinned to 03f1687fe6)
Solutions
- Move the JSON response to a nested route like `/api/+server.js` so the root serves an HTML page
- Add a root `+page.js`/`+page.svelte` that renders HTML at the base path
- Set `export const prerender = false` on the root +server.js route (and keep a separate prerendered root page)
- Use an adapter that supports server responses (adapter-node) instead of a static host
Example fix
// before — src/routes/+server.js
export const GET = () => json({ hello: 'world' });
// after — src/routes/api/+server.js
export const GET = () => json({ hello: 'world' });
// plus src/routes/+page.svelte rendering HTML at '/' Defensive patterns
Strategy: validation
Validate before calling
// pre-build check in a script
import { existsSync } from 'node:fs';
if (existsSync('src/routes/+server.js')) {
console.warn('Root +server.js exists; ensure its GET returns text/html or set prerender = false');
} Try / catch
try {
await build();
} catch (e) {
if (String(e.message).includes('root +server.js that returns a non-HTML')) {
console.error('Move your root endpoint to /api or add a root +page.svelte');
process.exit(1);
}
throw e;
} Prevention
- Keep JSON/API endpoints under a prefix like /api, never at the root
- Always ship a root +page.svelte for static hosts
- Audit root-level +server.js files before enabling full prerendering
When it happens
Trigger: A root-level `src/routes/+server.js` with `export const GET` returning json()/text (content-type other than text/html, status 200) while the whole app or that route is prerendered.
Common situations: adapter-static apps whose root returns an API-style JSON document; converting an SPA into a static build while keeping a JSON root endpoint.
Related errors
- Cannot read clientAddress during prerendering
- Could not create a fallback page
- Could not find prerendered page ${file} for route ${path}
- Cannot access cloudflare:workers in a prerenderable route
- The ${route.id} and ${existing.route_id} routes must be merg
AI-assisted analysis of sveltejs/kit@03f1687fe6 (2026-09-02).
Data as JSON: /api/errors/15ef3ba3bf7f1b5e.
Report an issue: GitHub.