sveltejs/kit · error

Cannot used reserved query parameter "${INVALIDATED_PARAM}"

Error message

Cannot used reserved query parameter "${INVALIDATED_PARAM}"

What it means

When the client fetches data it appends a reserved query parameter (__invalidated or similar INVALIDATED_PARAM) to communicate which stores need invalidation. If the developer's own URL already contains that parameter, appending it would corrupt the request, so DEV throws. This only guards the dev experience; it indicates the app is colliding with an internal protocol detail.

Source

Thrown at packages/kit/src/runtime/client/client.js:3676

		result.props.page.state = history_metadata?.persistState ? parse(history_metadata.state) : {};
	}

	await initialize(result, target, should_hydrate);
}

/**
 * @param {URL} url
 * @param {boolean[]} invalid
 * @returns {Promise<import('types').ServerNodesResponse | import('types').ServerRedirectNode>}
 */
async function load_data(url, invalid) {
	const data_url = new URL(url);
	data_url.pathname = add_data_suffix(url.pathname);
	if (url.pathname.endsWith('/')) {
		data_url.searchParams.append(TRAILING_SLASH_PARAM, '1');
	}
	if (DEV && url.searchParams.has(INVALIDATED_PARAM)) {
		throw new Error(`Cannot used reserved query parameter "${INVALIDATED_PARAM}"`);
	}
	data_url.searchParams.append(INVALIDATED_PARAM, invalid.map((i) => (i ? '1' : '0')).join(''));

	// use window.fetch directly to allow using a 3rd party-patched fetch implementation
	const fetcher = DEV ? dev_fetch : window.fetch;
	const res = await fetcher(data_url.href, {});

	// detect new deployments from the response header
	notify_version(res.headers.get('x-sveltekit-version'));

	if (!res.ok) {
		// if `__data.json` doesn't exist or the server has an internal error,
		// avoid parsing the HTML error page as a JSON
		/** @type {App.Error} */
		let error = { status: res.status, message: 'Internal Error' };

		if (res.headers.get('content-type')?.includes('application/json')) {
			error = { status: res.status, ...(await res.json()) };

View on GitHub (pinned to 03f1687fe6)

Solutions

  1. Remove the reserved parameter from URLs before passing to goto/fetch navigation
  2. Never persist/replay URLs taken from SvelteKit __data requests
  3. Rename your own query parameter if it collides with the internal key

Example fix

// before
const target = new URL(savedUrl); // contains ?__invalidated=1
await goto(target.href);
// after
const target = new URL(savedUrl);
target.searchParams.delete('__invalidated');
await goto(target.href);
Defensive patterns

Strategy: validation

Validate before calling

const RESERVED = '__invalidated'; // internal INVALIDATED_PARAM
function stripReservedParams(u) {
  const url = new URL(u, location.href);
  url.searchParams.delete(RESERVED);
  return url;
}
await goto(stripReservedParams(savedUrl).href);

Try / catch

try { await goto(url); } catch (e) { if (e.message.includes('reserved query parameter')) { const u = new URL(url, location.href); [...u.searchParams.keys()].forEach((k) => { if (k.startsWith('__')) u.searchParams.delete(k); }); await goto(u.href); } else { throw e; } }

Prevention

When it happens

Trigger: goto('/page?__invalidated=...') or navigating with a hand-built URL containing the reserved key; persisting a data-request URL (with the param) and re-navigating to it.

Common situations: Replaying URLs captured from network tab data-suffix requests; caching full request URLs including internal params; naming custom query params identically to the internal one.

Related errors


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