Skip to content

Conversation

@mandarini
Copy link
Contributor

What kind of change does this PR introduce?

Automatically initialize session on server client creation to trigger token refresh early in request lifecycle. This prevents race condition where refresh completes after response is sent, causing cookie errors. Also adds helpful error context before throwing if edge cases occur.

What is the current behavior?

Error: Cannot use `cookies.set(...)` after the response has been generated

Most possibly caused by token refresh.

What is the new behavior?

Initialize session to trigger token refresh early.

@mandarini mandarini force-pushed the fix/async-token-refresh-race-condition branch from dc11250 to 9c556eb Compare October 14, 2025 10:48
@mandarini mandarini requested a review from hf October 14, 2025 14:22
@mandarini mandarini self-assigned this Oct 14, 2025
Comment on lines +221 to +226
Promise.resolve().then(() => {
client.auth.getSession().catch(() => {
// Ignore errors - if session loading fails, the client is still usable
// and subsequent auth operations will handle the error appropriately
});
});
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm a bit scared of this as it runs all the time when the server gets created, but without the ability to set cookies if that's needed

Copy link
Contributor Author

@mandarini mandarini Oct 29, 2025

Choose a reason for hiding this comment

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

@hf Yeah I agree, it's a slippery slope. I wonder if there's a better way to treat this, and not get that race condition issue.

@ixxie
Copy link

ixxie commented Dec 14, 2025

@mandarini thanks for opening this, I'm running into this issue since I had to upgrade from Vite 5 => 7 in a SvelteKit project.

Important

Svelte and SvelteKit are moving really fast right now, since they have experimental support for async Svelte and SvelteKit remote functions. So SvelteKit users that want to keep dependencies up to day have to bump Vite to 7.

Is there a workaround I could do to the recommended approach from the docs to sidestep the issue? The best I could come up with (with Claude's help) is:

export const handle: Handle = async ({ event, resolve }) => {
  // Creates a Supabase client specific to this server request.
  // The Supabase client gets the Auth token from the request cookies.
  event.locals.supabase = createServerClient(
    PUBLIC_SUPABASE_URL,
    PUBLIC_SUPABASE_ANON_KEY,
    {
      cookies: {
        getAll: () => event.cookies.getAll(),
        // SvelteKit requires cookie `path` to be explicity set
        setAll: (cookiesToSet) => {
          cookiesToSet.forEach(({ name, value, options }) => {
            event.cookies.set(name, value, { ...options, path: '/' });
          });
        },
      },
    },
  );

  // Workaround for supabase/ssr#131: trigger token refresh early
  // before resolve() to prevent race condition with Vite 7
  await event.locals.supabase.auth.getSession();

  // Unlike `supabase.auth.getSession()`, which returns the session _without_
  // validating the JWT, this function also calls `getUser()` to validate the
  // JWT before returning the session.
  event.locals.safeGetSession = async () => {
    const {
      data: { session },
    } = await event.locals.supabase.auth.getSession();
    // no session
    if (!session) {
      return { session: null, user: null };
    }

    const {
      data: { user },
      error,
    } = await event.locals.supabase.auth.getUser();
    // no jwt token
    if (error) {
      return { session: null, user: null };
    }

    return { session, user };
  };

  return resolve(event, {
    filterSerializedResponseHeaders(name) {
      // forward supabase headers
      return name === 'content-range' || name === 'x-supabase-api-version';
    },
  });
};

@mandarini
Copy link
Contributor Author

Summoning @hf, maybe some better solution for @ixxie ?

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.

4 participants