remix-run/remix · critical · Error
Session cookie must be signed
Error message
Session cookie must be signed
What it means
The session() middleware requires the session cookie to be signed, because unsigned cookies can be forged by clients. It throws immediately at middleware construction time if cookie.signed is not enabled.
Source
Thrown at packages/session-middleware/src/lib/session.ts:17
import type { Cookie } from '@remix-run/cookie'
import type { Middleware } from '@remix-run/fetch-router'
import { Session, type SessionStorage } from '@remix-run/session'
/**
* Middleware that manages request session state on request context.
*
* @param sessionCookie The session cookie to use
* @param sessionStorage The storage backend for session data
* @returns The session middleware
*/
export function session(
sessionCookie: Cookie,
sessionStorage: SessionStorage,
): Middleware<{ key: typeof Session; value: Session; property: 'session' }> {
if (!sessionCookie.signed) {
throw new Error('Session cookie must be signed')
}
if (sessionCookie.httpOnly === false) {
console.warn(
`Session cookie "${sessionCookie.name}" is configured with httpOnly: false and may be accessible to client-side JavaScript.`,
)
}
return async (context, next) => {
if (context.has(Session)) {
throw new Error('Existing session found, refusing to overwrite')
}
let cookieValue = await sessionCookie.parse(context.headers.get('Cookie'))
let session = await sessionStorage.read(cookieValue)
context.set(Session, session, { property: 'session' })
View on GitHub (pinned to 9696913134)
Solutions
- Create the cookie with one or more secrets: cookie('session', { secrets: ['...'] })
- Ensure the secrets array is non-empty
- Load the secret from an environment variable rather than hardcoding
Example fix
// before
let cookie = createCookie('session', { path: '/' })
session(cookie, storage)
// after
let cookie = createCookie('session', { secrets: [process.env.SESSION_SECRET] })
session(cookie, storage) Defensive patterns
Strategy: validation
Validate before calling
if (!sessionCookie.signed) throw new Error('Configure cookie secrets before using session middleware') Prevention
- Always pass secrets when creating the session cookie
- Fail fast at startup on missing SESSION_SECRET env var
When it happens
Trigger: Calling session(cookie, storage) where the Cookie was created without a secret (or with signed: false), e.g. cookie('session', { path: '/' }) with no secrets option.
Common situations: Copying a plain cookie definition into session middleware setup; forgetting the secrets option when migrating from another session library; assuming signing is configured elsewhere.
Related errors
- Session cookie "${sessionCookie.name}" is configured with ht
- mounts keys must be URL pathnames without query strings, fra
- Resolved path escapes the allowed root: ${relativePath}
- trusted origin must not be empty
- invalid origin ${JSON.stringify(origin)}: trailing slash is
AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27).
Data as JSON: /api/errors/ef462b677abd85d3.
Report an issue: GitHub.