nuxt-modules / nuxt-modules/supabase

SSR session refresh crashes on Vercel node runtime: h3 v2 setCookie reads event.res.headers.getSetCookie() -> 504

Open
#642 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
935
Forks
157
Avg merge
7d 17h
Merged PRs (30d)
1

Description

Version

@nuxtjs/supabase: 2.0.10
nuxt: 4.4.8 (nitropack 2.13.4)
@supabase/ssr: 0.12.6
Deploy: Vercel (node runtime, NITRO_PRESET=vercel)
h3 versions in tree: 1.15.11 (nitro's dep) + 2.0.1-rc.20 / rc.22 (hoisted by other nuxt 4.4 deps)

Reproduction Link

No public repro repo (private production app), but the trigger is minimal and
described exactly below. Happy to build a minimal repro repo if the maintainers
need one.

Steps to reproduce
  1. Nuxt 4 app using @nuxtjs/supabase with SSR enabled (default server plugin
    path) deployed to Vercel with the node runtime.
  2. Load any SSR route with a browser that already holds a Supabase session
    cookie whose access token needs refreshing (e.g. session older than the
    token lifetime, or after an idle period — the supabase-js client refreshes
    and calls setAll to write the new cookies).
  3. The SSR request crashes before responding:
    TypeError: Cannot read properties of undefined (reading 'getSetCookie')
    inside h3's setCookie, reached via the module's cookie setAll handler.
  4. The unhandled rejection keeps the request hanging; Vercel kills the function
    at its 15s limit → 504 Gateway Timeout to the visitor.

Relevant stack (production log):

TypeError: Cannot read properties of undefined (reading 'getSetCookie')
    at setCookie (.../chunks/_/h3.mjs:272:43)
    at setCookies (.../chunks/build/server.mjs:22958:5)
    at setAll (.../chunks/build/server.mjs:23059:39)
    at setAll (.../chunks/build/server.mjs:22686:11)
    at applyServerStorage (.../chunks/build/server.mjs:22807:9)
    at SupabaseAuthClient._notifyAllSubscribers (.../chunks/build/server.mjs:20153:7)
Vercel Runtime Timeout Error: Task timed out after 15 seconds
What is Expected?

SSR requests that refresh a Supabase session should complete normally and the
refreshed cookies should be written to the response, on every deploy target —
including Vercel's node runtime.

What is actually happening?

The module's shared cookie util (dist/runtime/utils/cookies.js) writes auth
cookies through h3's setCookie/setHeader:

import { setCookie, setHeader } from 'h3'
// ...
setCookie(event, name, value, options)

h3 v1 (1.15.x, the version nitropack 2.13.4 declares) implements
setCookie node-safely — it writes via event.node.res.setHeader(...). h3
v2 rc (2.0.1-rc.20/rc.22, hoisted elsewhere in a nuxt 4.4 tree) rewrote
setCookie to Web-standard semantics:

const currentCookies = event.res.headers.getSetCookie()  // h3 v2

On the Vercel build the module's import ... from 'h3' resolves to the h3 v2
copy (separate chunk from nitro's node-safe v1 copy), but the runtime event
still carries a node-shaped res (ServerResponse — no .headers
property). So event.res.headers is undefined and getSetCookie throws —
inside supabase-js's session-refresh notification path, as an unhandled
rejection, leaving the request hanging until the platform timeout.

Related: the same file pair's getAll had the mirror-image crash on Vercel —
getHeader(event, 'Cookie') in h3 v2 reads event.req.headers.get(...) which
isn't a function on the node req — we patched that locally in 2026-09-08 with a
node-safe header read (event.node?.req ?? event.req), and hit this write-side
twin on 2026-09-10. Both halves trace to the module importing h3 helpers whose
node/web semantics diverged between h3 v1 and v2 without the module pinning
either.

Suggested fix direction

Write the cookies against the node response directly instead of routing through
h3's web-standard setCookie (mirroring h3 v1's own node-safe implementation):

// node-safe write: appendHeader handles repeated Set-Cookie correctly
response.appendHeader('Set-Cookie', serializeCookie(name, value, options))

where response = event.node.res (the module's setCookies already grabs it
for the writability check). Serialization should mirror cookie-es so the wire
format and the parse-side round-trip are unchanged. Our local patch does
exactly this and the Vercel build artifact is verified clean; a real upstream
fix would also pin or otherwise not depend on which h3 major resolves.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in dist/runtime/utils/cookies.js, especially setCookies and its use of h3 setCookie/setHeader, then inspect the node response already obtained for the writability check. Verify the cookie serialization and repeated Set-Cookie handling against the existing parse-side behavior. Done means an SSR session refresh completes on Vercel's node runtime without the getSetCookie error and refreshed cookies reach the response.

Written by the indexing model from the issue text.

Assessment

Tech stack
nuxt, typescript
Domain
authentication, backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.