sveltejs/kit · error · Error

Cannot use `setHeaders(...)` after the response has been gen

Error message

Cannot use `setHeaders(...)` after the response has been generated

What it means

Same guard as cookies.set: once resolve() has produced the Response, event.setHeaders is overwritten with a throwing function. Headers can no longer be applied to an already-built response, so the framework turns the no-op into a visible error.

Source

Thrown at packages/kit/src/runtime/server/respond.js:797

			// so we need to make an actual HTTP request
			const response = await fetch(request);

			// clone the response so that headers are mutable (https://github.com/sveltejs/kit/issues/13857)
			return new Response(response.body, response);
		} catch (e) {
			// TODO if `e` is instead named `error`, some fucked up Vite transformation happens
			// and I don't even know how to describe it. need to investigate at some point

			// HttpError from endpoint can end up here - TODO should it be handled there instead?
			return await handle_fatal_error(event, state, e);
		} finally {
			event.cookies.set = () => {
				throw new Error('Cannot use `cookies.set(...)` after the response has been generated');
			};

			// @ts-expect-error this has to be assigned lazily
			event.setHeaders = () => {
				throw new Error('Cannot use `setHeaders(...)` after the response has been generated');
			};
		}
	}
}

/**
 * @param {import('types').PageNodeIndexes} page
 */
export function load_page_nodes(page) {
	return Promise.all([
		// we use == here rather than === because [undefined] serializes as "[null]"
		...page.layouts.map((n) => (n == undefined ? n : manifest.nodes[n]())),
		manifest.nodes[page.leaf]()
	]);
}

/**
 * It's likely that, in a distributed system, there are spans starting outside the SvelteKit server -- eg.

View on GitHub (pinned to 03f1687fe6)

Solutions

  1. Call setHeaders synchronously within the load function, action, endpoint handler, or before resolve(event) in the handle hook
  2. For streamed chunks, set headers on the individual chunk Response rather than via event.setHeaders
  3. Audit async helpers for deferred setHeaders calls and pass header values back to the main handler instead

Example fix

// before
export const load = async (event) => {
  setTimeout(() => event.setHeaders({ 'cache-control': 'no-cache' }), 0); // throws
  return { data };
};
// after
export const load = async (event) => {
  event.setHeaders({ 'cache-control': 'no-cache' });
  return { data };
};
Defensive patterns

Strategy: try-catch

Validate before calling

function canSetHeaders(event) {
  try { event.setHeaders({}); return true; } catch { return false; }
}

Try / catch

try {
  event.setHeaders({ 'cache-control': 'no-store' });
} catch {
  // too late in lifecycle; set headers earlier or on the chunk Response
  console.warn('setHeaders called after response generated');
}

Prevention

When it happens

Trigger: Calling event.setHeaders inside a streaming promise callback, a detached async continuation, or an after-response hook; calling setHeaders in code invoked from a setTimeout after the handler returns.

Common situations: Attempt to set cache-control after a slow stream starts; refactored shared helper that receives event and calls setHeaders, invoked post-resolution.

Related errors


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