{"record":{"id":"49ac895bbf6d2f90","repo":"sveltejs/kit","slug":"cannot-use-cookies-set-after-the-response-h","errorCode":null,"errorMessage":"Cannot use `cookies.set(...)` after the response has been generated","messagePattern":"Cannot use `cookies\\.set\\(\\.\\.\\.\\)` after the response has been generated","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/kit/src/runtime/server/respond.js","lineNumber":792,"sourceCode":"\t\t\tif (state.prerendering) {\n\t\t\t\treturn text('not found', { status: 404 });\n\t\t\t}\n\n\t\t\t// we can't load the endpoint from our own manifest,\n\t\t\t// so we need to make an actual HTTP request\n\t\t\tconst response = await fetch(request);\n\n\t\t\t// clone the response so that headers are mutable (https://github.com/sveltejs/kit/issues/13857)\n\t\t\treturn new Response(response.body, response);\n\t\t} catch (e) {\n\t\t\t// TODO if `e` is instead named `error`, some fucked up Vite transformation happens\n\t\t\t// and I don't even know how to describe it. need to investigate at some point\n\n\t\t\t// HttpError from endpoint can end up here - TODO should it be handled there instead?\n\t\t\treturn await handle_fatal_error(event, state, e);\n\t\t} finally {\n\t\t\tevent.cookies.set = () => {\n\t\t\t\tthrow new Error('Cannot use `cookies.set(...)` after the response has been generated');\n\t\t\t};\n\n\t\t\t// @ts-expect-error this has to be assigned lazily\n\t\t\tevent.setHeaders = () => {\n\t\t\t\tthrow new Error('Cannot use `setHeaders(...)` after the response has been generated');\n\t\t\t};\n\t\t}\n\t}\n}\n\n/**\n * @param {import('types').PageNodeIndexes} page\n */\nexport function load_page_nodes(page) {\n\treturn Promise.all([\n\t\t// we use == here rather than === because [undefined] serializes as \"[null]\"\n\t\t...page.layouts.map((n) => (n == undefined ? n : manifest.nodes[n]())),\n\t\tmanifest.nodes[page.leaf]()","sourceCodeStart":774,"sourceCodeEnd":810,"githubUrl":"https://github.com/sveltejs/kit/blob/03f1687fe612ce3d2d9131139b5b188d9cf90c64/packages/kit/src/runtime/server/respond.js#L774-L810","documentation":"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.","triggerScenarios":"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.","commonSituations":"Deferred analytics/session refresh code that runs after await resolve(); setting cookies in an after() hook or in a streaming promise's callback.","solutions":["Move cookies.set calls into the main body of your load function, action, or handle hook before the promise resolves","Use the new handle hook's event.cookies before calling resolve(event), or use the locals pattern to defer state without cookies","If you must react after the response, restructure to set the cookie in an API endpoint/action called from the client"],"exampleFix":"// before\nexport const load = async ({ cookies }) => {\n  stream(() => cookies.set('seen', '1', { path: '/' })); // throws later\n  return { data };\n};\n// after\nexport const load = async ({ cookies }) => {\n  cookies.set('seen', '1', { path: '/' });\n  return { data };\n};","handlingStrategy":"try-catch","validationCode":"function canSetCookies(event) {\n  return typeof event.cookies.set === 'function' && !event.cookies.set.toString().includes('throw');\n}","typeGuard":null,"tryCatchPattern":"try {\n  cookies.set('sid', value, { path: '/' });\n} catch {\n  // response already generated — move cookie setting earlier in the request lifecycle\n  console.warn('cookies.set called after response; setting skipped');\n}","preventionTips":["Set cookies only at the top level of load/actions/handle, never in detached promises","Avoid cookies.set inside streamed promises or after await points that outlive the handler","Centralize cookie logic in the handle hook before resolve(event)"],"tags":["cookies","sveltekit","lifecycle"],"backgroundTag":"cookie-set-after-response","analyzedSha":"03f1687fe612ce3d2d9131139b5b188d9cf90c64","analyzedAt":"2026-09-02T02:01:50.504Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}