withastro/astro · warning
Astro.cookies.set() was called after the cookies had already
Error message
Astro.cookies.set() was called after the cookies had already been sent to the browser. This may have happened if this method was called in an imported component. Please make sure that Astro.cookies.set() is only called in the frontmatter of the main page.
What it means
Astro serializes cookies into Set-Cookie headers when the response is finalized (cookies marked consumed). A cookies.set() after that point cannot reach the browser, so Astro builds a Warning-named Error, prints it via console.warn, and the new cookie value never reaches the client.
Source
Thrown at packages/astro/src/core/cookies/cookies.ts:173
let [, , isSetValue] = this.#outgoing.get(key)!;
return isSetValue;
}
const values = this.#ensureParsed();
return values[key] !== undefined;
}
/**
* Astro.cookies.set(key, value) is used to set a cookie's value. If provided
* an object it will be stringified via JSON.stringify(value). Additionally you
* can provide options customizing how this cookie will be set, such as setting httpOnly
* in order to prevent the cookie from being read in client-side JavaScript.
* @param key The name of the cookie to set.
* @param value A value, either a string or other primitive or an object.
* @param options Options for the cookie, such as the path and security settings.
*/
set(key: string, value: string | Record<string, any>, options?: AstroCookieSetOptions): void {
if (this.#consumed) {
this.#logger.warn(
'SKIP_FORMAT',
'Astro.cookies.set() was called after the cookies had already been sent to the browser.\n' +
'This may have happened if this method was called in an imported component.\n' +
'Please make sure that Astro.cookies.set() is only called in the frontmatter of the main page.',
);
}
let serializedValue: string;
if (typeof value === 'string') {
serializedValue = value;
} else {
// Support stringifying JSON objects for convenience. First check that this is
// a plain object and if it is, stringify. If not, allow support for toString() overrides.
let toStringValue = value.toString();
if (toStringValue === Object.prototype.toString.call(value)) {
serializedValue = JSON.stringify(value);
} else {
serializedValue = toStringValue;
}View on GitHub (pinned to e294953aa8)
Solutions
- Move Astro.cookies.set() into the frontmatter of the top-level page or an API route, before any output is written
- For cross-page cookie logic, use src/middleware.ts and call context.cookies.set() in onRequest before next()
- If the value is only needed client-side, set document.cookie from a <script> instead
Example fix
<!-- before — src/components/SetTheme.astro, imported into many pages -->
---
Astro.cookies.set('theme', 'dark');
---
// after — src/middleware.ts: cookies set before any rendering
export const onRequest = (context, next) => {
context.cookies.set('theme', 'dark', { path: '/' });
return next();
}; Defensive patterns
Strategy: validation
Validate before calling
# CI guard: cookies.set must not appear inside components ! grep -rn "cookies.set" src/components && echo OK
Prevention
- Centralize cookie writes in src/middleware.ts or page/API-route frontmatter only
- Never call Astro.cookies.set() in imported components — they render after headers may be sent
- Set cookies before awaiting any render/streaming work
When it happens
Trigger: Astro.cookies.set() runs after #consumed was set — typically inside a component's frontmatter that renders after the page's cookies were already sent, in code that runs during/after response streaming, or in a deferred callback after the response completed.
Common situations: Moving cookie logic into a shared layout/component imported by many pages; setting cookies inside render-time utilities or async components that resolve after the stream began.
Related errors
- ResponseSentError
- ResponseSentError
- [astro:cache] Skipping cache for ${url.pathname}${url.search
- NoImageMetadata
- ResponseSentError
AI-assisted analysis of withastro/astro@e294953aa8 (2026-09-09).
Data as JSON: /api/errors/b9968972ad017419.
Report an issue: GitHub.