sveltejs/kit · error · Error

Failed to get response header "${lower}" — it must be includ

Error message

Failed to get response header "${lower}" — it must be included by the `filterSerializedResponseHeaders` option: https://svelte.dev/docs/kit/hooks#handle (at ${event.route.id})

What it means

During server-side rendering, universal-load fetch responses are serialized to the client with only a whitelisted set of headers. Reading a header via `response.headers.get()` that `filterSerializedResponseHeaders` (in `handle` in hooks.server.js) doesn't approve throws this error, since the header would be absent on the client and cause hydration mismatches.

Source

Thrown at packages/kit/src/runtime/server/page/load_data.js:463

							length: { value: value.length }
						}
					);
				}

				return value;
			}
		});

		if (csr) {
			// ensure that excluded headers can't be read
			const get = response.headers.get;
			response.headers.get = (key) => {
				const lower = key.toLowerCase();
				const value = get.call(response.headers, lower);
				if (value && !lower.startsWith('x-sveltekit-')) {
					const included = resolve_opts.filterSerializedResponseHeaders(lower, value);
					if (!included) {
						throw new Error(
							`Failed to get response header "${lower}" — it must be included by the \`filterSerializedResponseHeaders\` option: https://svelte.dev/docs/kit/hooks#handle (at ${event.route.id})`
						);
					}
				}

				return value;
			};

			const get_set_cookie = response.headers.getSetCookie;
			response.headers.getSetCookie = () => {
				const values = get_set_cookie.call(response.headers);
				for (const value of values) {
					const included = resolve_opts.filterSerializedResponseHeaders('set-cookie', value);
					if (!included) {
						throw new Error(
							`Failed to get response header "set-cookie" — it must be included by the \`filterSerializedResponseHeaders\` option: https://svelte.dev/docs/kit/hooks#handle (at ${event.route.id})`
						);
					}

View on GitHub (pinned to 03f1687fe6)

Solutions

  1. In hooks.server.js `handle`, set `event.setHeaders` appropriately and add the header name to `filterSerializedResponseHeaders`: return true for the headers you need serialized
  2. Move the fetch to a server-only load (`+page.server.js`) where headers are fully accessible
  3. Read the data via your own `+server.js` proxy that returns the value in the JSON body instead of a header

Example fix

// hooks.server.js (before)
filterSerializedResponseHeaders: () => false;
// after
filterSerializedResponseHeaders: (name) => name.startsWith('x-pagination-');
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const count = res.headers.get('x-total-count');
  return { items, count: count ? Number(count) : null };
} catch (e) {
  if (String(e).includes('filterSerializedResponseHeaders')) {
    return { items, count: null }; // header not whitelisted
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling `response.headers.get('some-header')` inside a universal load on a cross-origin fetch where `filterSerializedResponseHeaders(name, value)` returns false (default rejects all non-`x-sveltekit-` headers).

Common situations: Reading `ratelimit-*`, `x-total-count`, or custom pagination headers from an API in `+page.js` load; forgetting to add the header to the whitelist in `handle` in hooks.server.js after adding new header reads.

Related errors


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