sveltejs/kit · error · Error

Cannot use `cookies.set(...)` after the response has been ge

Error message

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

What it means

After SvelteKit has generated the Response (in the finally block of resolve), event.cookies.set is replaced with a throwing stub. Mutating cookies after the response is serialized would silently do nothing, so the framework makes it an explicit error. This guards the boundary between request handling and response finalization.

Source

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

			if (state.prerendering) {
				return text('not found', { status: 404 });
			}

			// we can't load the endpoint from our own manifest,
			// 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]()

View on GitHub (pinned to 03f1687fe6)

Solutions

  1. Move cookies.set calls into the main body of your load function, action, or handle hook before the promise resolves
  2. Use the new handle hook's event.cookies before calling resolve(event), or use the locals pattern to defer state without cookies
  3. If you must react after the response, restructure to set the cookie in an API endpoint/action called from the client

Example fix

// before
export const load = async ({ cookies }) => {
  stream(() => cookies.set('seen', '1', { path: '/' })); // throws later
  return { data };
};
// after
export const load = async ({ cookies }) => {
  cookies.set('seen', '1', { path: '/' });
  return { data };
};
Defensive patterns

Strategy: try-catch

Validate before calling

function canSetCookies(event) {
  return typeof event.cookies.set === 'function' && !event.cookies.set.toString().includes('throw');
}

Try / catch

try {
  cookies.set('sid', value, { path: '/' });
} catch {
  // response already generated — move cookie setting earlier in the request lifecycle
  console.warn('cookies.set called after response; setting skipped');
}

Prevention

When it happens

Trigger: Calling cookies.set inside a fire-and-forget promise, a streamed promise (</script> stream callback), or code scheduled after the load/endpoint handler resolves but executed while response finalization runs.

Common situations: Deferred analytics/session refresh code that runs after await resolve(); setting cookies in an after() hook or in a streaming promise's callback.

Related errors


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