Skip to content

fix: avoid duplicate cache headers per server client - #283

Open
dhruvxvaishnav wants to merge 2 commits into
supabase:mainfrom
dhruvxvaishnav:fix/sveltekit-duplicate-cache-headers
Open

fix: avoid duplicate cache headers per server client#283
dhruvxvaishnav wants to merge 2 commits into
supabase:mainfrom
dhruvxvaishnav:fix/sveltekit-duplicate-cache-headers

Conversation

@dhruvxvaishnav

Copy link
Copy Markdown

What kind of change does this PR introduce?

Bug fix.

Fixes #279.

What is the current behavior?

Starting an email PKCE flow with signInWithOtp() writes the per-flow verifier, flow index, and legacy verifier cookies in separate batches. Each batch currently carries the same cache-prevention headers to setAll.

Frameworks that overwrite repeated response headers tolerate this, but SvelteKit's event.setHeaders() rejects a second assignment of the same header during one request, causing the auth operation to fail with "Cache-Control" header is already set.

What is the new behavior?

Every cookie batch is still forwarded to setAll, while non-empty cache-prevention headers are forwarded only once for the lifetime of a request-scoped server client. Later calls receive an empty headers object because the response has already been marked as non-cacheable.

A regression test exercises the full createServerClient().auth.signInWithOtp() path with a strict SvelteKit-style callback. It verifies that all three cookie batches are preserved without assigning any response header twice.

Additional context

The cache headers were introduced in #176 to prevent auth responses from being cached by CDNs. This change preserves that protection because response headers apply to the whole response rather than to an individual cookie batch.

Validation:

  • pnpm exec prettier --check .
  • pnpm exec eslint
  • pnpm build
  • pnpm test -- --run (109 tests passed)
  • git diff --check

AI assistance disclosure: OpenAI Codex assisted with codebase exploration, implementation support, regression-test preparation, code review, and validation. I remain responsible for understanding and maintaining this contribution.

@dhruvxvaishnav
dhruvxvaishnav requested review from a team as code owners August 14, 2026 16:27

@mandarini mandarini left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @dhruvxvaishnav, thank you so much for this! The fix looks great and the regression test is exactly what was needed. One thing before I merge: since the headers are now sent only once per client instance, could you make that constraint explicit in the SetAllCookies JSDoc in types.ts? Something along the lines of: the cache headers are delivered on the first cookie write from a server client, so a client must be created fresh for each request, otherwise later responses will miss these headers. Right now the doc says the object is empty on later calls but not why reusing a client across requests would be a problem.

Thanks again for taking this on!

@dhruvxvaishnav

Copy link
Copy Markdown
Author

Thank you for the clear feedback! I updated the SetAllCookies JSDoc to state that a server client delivers cache headers only with its first cookie write and must be created fresh for every request; otherwise later responses could miss the required cache headers. I also clarified that subsequent calls from the same client receive an empty headers object. Local formatting, linting, builds, all 109 tests, and git diff checks pass.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

event.setHeaders() throws "header is already set" when signInWithOtp() writes PKCE verifier cookie in SvelteKit

2 participants