withastro/astro · error · AstroError

ResponseSentError

ResponseSentError

Error message

The response has already been sent to the browser and cannot be altered.

What it means

`Astro.cookies.set()` records the outgoing cookie but then checks a `responseSent` symbol on the request; if the response has already been flushed to the browser, mutating cookies is impossible, so Astro throws `ResponseSentError`. This prevents silently losing a cookie the developer believed was set.

Source

Thrown at packages/astro/src/core/cookies/cookies.ts:208

		}

		const { encode, ...attributes } = options ?? {};

		this.#ensureOutgoingMap().set(key, [
			serializedValue,
			stringifySetCookie(
				{
					...attributes,
					name: key,
					value: serializedValue,
				},
				{ encode },
			),
			true,
		]);

		if ((this.#request as any)[responseSentSymbol]) {
			throw new AstroError({
				...AstroErrorData.ResponseSentError,
			});
		}
	}

	/**
	 * Merges a new AstroCookies instance into the current instance. Any new cookies
	 * will be added to the current instance, overwriting any existing cookies with the same name.
	 */
	merge(cookies: AstroCookies) {
		const outgoing = cookies.#outgoing;
		if (outgoing) {
			for (const [key, value] of outgoing) {
				this.#ensureOutgoingMap().set(key, value);
			}
		}
	}

View on GitHub (pinned to d081033d5f)

Solutions

  1. Set all cookies before sending the response (before `return Astro.redirect(...)`, `Response.json(...)`, etc.).
  2. Restructure control flow so cookie writes happen at the top of the handler.
  3. Avoid long `await`s between setting a cookie and returning; move cookie logic earlier.

Example fix

// before
return Astro.redirect('/login', 302);
Astro.cookies.set('flash', 'error'); // unreachable / post-send

// after
Astro.cookies.set('flash', 'error');
return Astro.redirect('/login', 302);
Defensive patterns

Strategy: validation

Validate before calling

// Set cookies before any response-sending call.
Astro.cookies.set('k', 'v');
return Astro.redirect('/next');

Try / catch

try { Astro.cookies.set('k', 'v'); } catch (e) { if (e.code === 'ResponseSentError') { /* too late; log */ } else throw e; }

Prevention

When it happens

Trigger: Calling `Astro.cookies.set(...)` after `Astro.response.send(...)`/`redirect(...)`/`Response.json(...)` in the same request, or in middleware after the response body has been streamed. The check at `cookies.ts:208` fires on the next `set`.

Common situations: Returning early from a handler and then conditionally setting a cookie in code that runs after; calling `set` inside an `await` chain that completes after streaming started; middleware that sets cookies after `next()` streamed the body.

Related errors


AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12). Data as JSON: /api/errors/25602c345dadfad6. Report an issue: GitHub.