sveltejs/kit · warning

Avoid calling `fetch` eagerly during server-side rendering —

Error message

Avoid calling `fetch` eagerly during server-side rendering — put your `fetch` calls inside `onMount` or a `load` function instead

What it means

During SSR, SvelteKit temporarily replaces globalThis.fetch so it can intercept relative-URL requests made while rendering a component (which has no proper base URL on the server). If component-level code calls fetch with a relative URL during SSR, or an absolute-URL call happens outside a load function/remote function context, SvelteKit warns that the call must be moved into onMount or a load function. It is a console warning, not a thrown error, unless the URL is relative, in which case it throws an Error.

Source

Thrown at packages/kit/src/runtime/server/page/render.js:235

						props.page.status = status = error.status;

						return error;
					}
				: undefined
		};

		const fetch = globalThis.fetch;

		try {
			if (DEV) {
				let warned = false;
				globalThis.fetch = (info, init) => {
					if (typeof info === 'string' && !SCHEME.test(info)) {
						throw new Error(
							`Cannot call \`fetch\` eagerly during server-side rendering with relative URL (${info}) — put your \`fetch\` calls inside \`onMount\` or a \`load\` function instead`
						);
					} else if (!warned && !try_get_request_store()?.state.is_in_remote_function) {
						console.warn(
							'Avoid calling `fetch` eagerly during server-side rendering — put your `fetch` calls inside `onMount` or a `load` function instead'
						);
						warned = true;
					}

					return fetch(info, init);
				};
			}

			rendered = await with_request_store({ event, state: render_state }, async () => {
				return render(Root, { ...render_opts, props });
			});

			if (rendered.hashes) {
				csp.add_script_hashes(rendered.hashes.script);
			}
		} finally {
			if (DEV) {

View on GitHub (pinned to 03f1687fe6)

Solutions

  1. Move the fetch call into a load function (+page.js or +page.server.js) and return the data
  2. Wrap the call in onMount (or equivalent browser-only lifecycle) so it only runs on the client
  3. Use an absolute URL (including scheme) if the fetch must run during SSR outside load
  4. Guard with `if (browser)` from '$app/environment' before calling fetch

Example fix

<!-- before: +page.svelte -->
<script>
  const data = await fetch('/api/items').then((r) => r.json());
</script>

<!-- after: +page.js -->
export async function load({ fetch }) {
  return { items: await fetch('/api/items').then((r) => r.json()) };
}
Defensive patterns

Strategy: validation

Validate before calling

import { browser } from '$app/environment';
if (!browser && !inLoadContext()) {
  throw new Error('move this fetch into a load function or onMount');
}

Type guard

function canFetchDuringSSR(url) {
  return typeof url === 'string' ? /^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(url) : true;
}

Prevention

When it happens

Trigger: Calling fetch('relative/path') at the top level of a +page.svelte/+layout.svelte during SSR (throws); calling fetch eagerly in module scope or component init with any URL while not inside a load function or remote function (warns once); after a SvelteKit upgrade, globalThis.fetch is wrapped only during render_response so eager calls are detected.

Common situations: Porting client-only components to SSR without guards; data fetching written directly in a component body instead of +page.js/+page.server.js load; code shared between browser and server that fetches relative endpoints like '/api/x'; using fetch in a context where try_get_request_store() is undefined so the interceptor cannot resolve relative URLs.

Related errors


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