sveltejs/kit · warning
\u001B[1m\u001B[31mReturning promises from server `load` fun
Error message
\u001B[1m\u001B[31mReturning promises from server `load` functions will only work if `csr === true`\u001B[39m\u001B[22m
What it means
When csr is false, SvelteKit serializes the server render to static HTML with no client runtime, so there is no way to resolve promises returned from server load functions after the initial stream. In dev, if the page's server load returned promises (deferred streaming) and csr is disabled, SvelteKit warns that this pattern only works with csr === true.
Source
Thrown at packages/kit/src/runtime/server/page/render.js:648
done: true
})) || '';
if (!chunks) {
headers.set('etag', `"${hash(transformed)}"`);
}
if (DEV) {
if (page_config.csr) {
if (count_non_ssi_comments(transformed) < count_non_ssi_comments(html)) {
// the \u001B stuff is ANSI codes, so that we don't need to add a library to the runtime
// https://svelte.dev/playground/1b3f49696f0c44c881c34587f2537aa2?version=4.2.19
console.warn(
"\u001B[1m\u001B[31mRemoving comments in transformPageChunk can break Svelte's hydration\u001B[39m\u001B[22m"
);
}
} else {
if (chunks) {
console.warn(
'\u001B[1m\u001B[31mReturning promises from server `load` functions will only work if `csr === true`\u001B[39m\u001B[22m'
);
}
}
}
return chunks
? new Response(stream_text(transformed + '\n', chunks), { status, headers })
: text(transformed, { status, headers });
}
class Head {
#rendered;
/** @type {string[]} */
#http_equiv = [];
/** @type {string[]} */
#link_tags = [];
/** @type {string[]} */View on GitHub (pinned to 03f1687fe6)
Solutions
- Set `export const csr = true` for routes whose server load returns promises
- Resolve all promises before returning from server load (await everything) so nothing is deferred
- Split the route: a static csr=false page without streaming plus a separate csr=true page for streamed data
Example fix
// before (+page.server.js, csr=false elsewhere)
export async function load() {
return { comments: getComments() }; // promise
}
// after
export async function load() {
return { comments: await getComments() };
} Defensive patterns
Strategy: validation
Validate before calling
// ensure no promise values returned when csr is false
export const csr = false;
// in load: assert every returned value is not a thenable
Object.entries(result).forEach(([k, v]) => {
if (v && typeof v.then === 'function') throw new Error(`${k} must be awaited when csr=false`);
}); Type guard
function isThenable(v) { return !!v && typeof v.then === 'function'; } Prevention
- Never mix csr=false with streaming load returns
- Await all promises in server load when csr is disabled
- Document per-route csr setting near the load function
When it happens
Trigger: A +page.server.js (or +layout.server.js) load returns an object containing promise values (streaming pattern like { streamed: getStuff() }) while the route sets `export const csr = false`; occurs during dev SSR of a chunk set.
Common situations: Enabling prerendering/SPA-less output (csr = false) on routes that also use streaming load; migrating a streamed-data page to fully static output; docs example of csr=false combined with async load results.
Related errors
- The form action returned an error, but +error.svelte wasn't
- Loading ${url} using `window.fetch`. For best results, use t
- Cannot access cloudflare:workers in a prerenderable route
- The configured Vite SSR environment must be a RunnableDevEnv
- ${prerendered.error}
AI-assisted analysis of sveltejs/kit@03f1687fe6 (2026-09-02).
Data as JSON: /api/errors/49b65b4c48ba1e23.
Report an issue: GitHub.