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

  1. Store only small identifiers (userId, flags) in the cookie session and keep bulky data server-side
  2. Switch to a server-backed session storage (DatabaseSessionStorage or a custom SessionStorage keyed by session id)
  3. unset() flash/single-use keys right after reading them in the loader
  4. 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

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)