remix-run/react-router · error
Cookie length will exceed browser maximum. Length
Error message
Cookie length will exceed browser maximum. Length: ${serializedCookie.length} What it means
Browsers cap a single cookie at 4096 bytes, and cookie-based sessions (createCookieSessionStorage) must fit the whole session into that one cookie. commitSession (lib/server-runtime/sessions/cookieStorage.ts:56) serializes then measures, and throws with the offending length so you find out at commit time instead of silently losing the session in the browser.
Solutions
- Store only small identifiers (userId, flags) in the cookie session and keep bulky data server-side
- Switch to a server-backed session storage (DatabaseSessionStorage or a custom SessionStorage keyed by session id)
- unset() flash/single-use keys right after reading them in the loader
- Audit session.data contents and remove keys you no longer write
Example fix
// before
session.set('user', user) // whole profile -> >4KB after signing
// after
session.set('userId', user.id)
// load the rest from the DB in the loader Defensive patterns
Strategy: validation
Validate before calling
// Check size before committing
const serialized = await cookie.serialize(session.data);
if (serialized.length > 4096) {
// trim or move to server-side storage before commitSession
session.unset(' bulkyKey');
}
const setCookie = await commitSession(session); Try / catch
try {
return json(data, { headers: { 'Set-Cookie': await commitSession(session) } });
} catch (e) {
if (e instanceof Error && e.message.includes('browser maximum')) {
// drop non-essential keys and retry once
session.unset('flash');
return json(data, { headers: { 'Set-Cookie': await commitSession(session) } });
}
throw e;
} Prevention
- Keep only ids/flags in cookie sessions; store payloads server-side keyed by session id
- unset() flash and one-time keys immediately after reading
- Unit-test session size for your largest realistic payloads
- Use DatabaseSessionStorage once data exceeds a few hundred bytes
When it happens
Trigger: session.set() with large objects (user profiles, tokens, arrays, base64 blobs); flash messages accumulating without unset; growing key sets over a long-lived session; encrypted cookies where the signature/ciphertext inflates the payload.
Common situations: Storing OAuth/JWT payloads or whole API responses in the session; e-commerce carts kept in the session cookie; forgetting session.unset() after reading flash data.
AI-assisted analysis of remix-run/react-router@6beaca3952 (2026-08-18).
Data as JSON: /api/errors/17573490aa65f297.
Report an issue: GitHub.
Appendix: source
Thrown at packages/react-router/lib/server-runtime/sessions/cookieStorage.ts:56
Data,
FlashData
> {
let cookie = isCookie(cookieArg)
? cookieArg
: createCookie(cookieArg?.name || "__session", cookieArg);
warnOnceAboutSigningSessionCookie(cookie);
return {
async getSession(cookieHeader, options) {
return createSession(
(cookieHeader && (await cookie.parse(cookieHeader, options))) || {},
);
},
async commitSession(session, options) {
let serializedCookie = await cookie.serialize(session.data, options);
if (serializedCookie.length > 4096) {
throw new Error(
"Cookie length will exceed browser maximum. Length: " +
serializedCookie.length,
);
}
return serializedCookie;
},
async destroySession(_session, options) {
return cookie.serialize("", {
...options,
maxAge: undefined,
expires: new Date(0),
});
},
};
}
View on GitHub (pinned to 6beaca3952)