nextauthjs/next-auth · error · TypeError

option sameSite is invalid: ${options.sameSite}

Error message

option sameSite is invalid: ${options.sameSite}

What it means

serialize() accepts `sameSite` only as true, 'strict', 'lax', or 'none' (strings are matched case-insensitively after lowercasing). Any other truthy value — e.g. 'default', a number, or a random string — hits the default branch and throws a TypeError. SameSite is a closed enum in the cookie spec, so the library fails fast rather than emitting an attribute browsers would ignore.

Source

Thrown at packages/core/src/lib/vendored/cookie.ts:358

  if (options.sameSite) {
    const sameSite =
      typeof options.sameSite === "string"
        ? options.sameSite.toLowerCase()
        : options.sameSite
    switch (sameSite) {
      case true:
      case "strict":
        str += "; SameSite=Strict"
        break
      case "lax":
        str += "; SameSite=Lax"
        break
      case "none":
        str += "; SameSite=None"
        break
      default:
        throw new TypeError(`option sameSite is invalid: ${options.sameSite}`)
    }
  }

  return str
}

/**
 * URL-decode string value. Optimized to skip native call when no %.
 */
function decode(str: string): string {
  if (str.indexOf("%") === -1) return str

  try {
    return decodeURIComponent(str)
  } catch (e) {
    return str
  }
}

View on GitHub (pinned to a1a16a5a77)

Solutions

  1. Use one of: true/'strict', 'lax', or 'none' (case-insensitive)
  2. Remember SameSite=None additionally requires the Secure attribute in modern browsers
  3. Add a TS union type: sameSite?: true | 'strict' | 'lax' | 'none' to catch bad values at compile time
  4. Map external frameworks' values to this library's accepted set before calling serialize

Example fix

// before
serialize('sid', val, { sameSite: 'unspecified' })
// after
serialize('sid', val, { sameSite: 'lax' })
Defensive patterns

Strategy: type-guard

Validate before calling

const SAME_SITE = new Set(['strict', 'lax', 'none', 'true'])
function isValidSameSite(v) {
  if (v === true) return true
  return typeof v === 'string' && SAME_SITE.has(v.toLowerCase())
}
if (opts.sameSite && !isValidSameSite(opts.sameSite)) throw new TypeError(`option sameSite is invalid: ${opts.sameSite}`)

Type guard

type SameSite = true | 'strict' | 'lax' | 'none'
function isSameSite(v: unknown): v is SameSite {
  return v === true || (typeof v === 'string' && ['strict', 'lax', 'none'].includes(v.toLowerCase()))
}

Try / catch

let cookie
try {
  cookie = serialize('sid', val, { sameSite })
} catch (err) {
  if (err instanceof TypeError && err.message.startsWith('option sameSite is invalid')) {
    throw new ConfigError(`Invalid sameSite '${sameSite}' — use strict, lax, or none`)
  }
  throw err
}

Prevention

When it happens

Trigger: serialize(name, val, { sameSite: 'default' }), { sameSite: 'auto' }, { sameSite: 1 }, or copying a SameSite value from another framework that uses different casing/values not in the accepted set.

Common situations: Migrating from older cookie libs whose enum included 'none' variants or 'unspecified'; reading sameSite from config/env where authors wrote 'no_restriction' or 'strict_but_ok'; passing the browser's parsed SameSite string in unexpected form; typos like 'laxt'.

Related errors


AI-assisted analysis of nextauthjs/next-auth@a1a16a5a77 (2026-08-28). Data as JSON: /api/errors/ae7f03e5f900494f. Report an issue: GitHub.