auth.api.getSession returns null in RSC Layout.tsx with valid session #947

Closed
opened 2026-03-13 08:11:07 -05:00 by GiteaMirror · 68 comments
Owner

Originally created by @ian on GitHub (Mar 30, 2025).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

I'm trying to debug why auth.api.getSession will return null, when the session is valid after a query to /api/auth/get-session.

Consider the following src/app/layout.tsx:

import { Providers } from '@/components/providers';
import { auth } from '@/auth';
import { Analytics } from '@vercel/analytics/react';
import { headers } from 'next/headers';

export default async function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  const session = await auth.api.getSession({
    headers: await headers(),
  });

  console.debug('RootLayout', { session });

  return (
    <html lang="en" suppressHydrationWarning>
      <body>
        <Providers>{children}</Providers>
        <Analytics />
      </body>
    </html>
  );
}

Current vs. Expected behavior

One would expect to see "RootLayout: { session: { ... } }" but instead, the session is null.

I can see the session token in the requests:

Image

And requests to /api/auth/get-session return a valid session:

Image

What version of Better Auth are you using?

1.2.5

Provide environment information

- OS: MacOS
- Browser: Chrome

Which area(s) are affected? (Select all that apply)

Backend

Auth config (if applicable)

export const auth = betterAuth({
  basePath: '/auth',
  database: prismaAdapter(prisma, {
    provider: 'postgresql',
  }),
  plugins: [
    emailOTP({
      sendVerificationOTP,
    }),
    nextCookies(),
    expo(),
  ],
  socialProviders: {
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID as string,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
    },
  },
  user: {
    additionalFields: {
      role: {
        type: 'string',
        required: false,
        defaultValue: 'user',
        input: false,
      },
      lang: {
        type: 'string',
        required: false,
        defaultValue: 'en',
      },
    },
  },
});

Additional context

No response

Originally created by @ian on GitHub (Mar 30, 2025). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce I'm trying to debug why `auth.api.getSession` will return null, when the session is valid after a query to /api/auth/get-session. Consider the following src/app/layout.tsx: ```ts import { Providers } from '@/components/providers'; import { auth } from '@/auth'; import { Analytics } from '@vercel/analytics/react'; import { headers } from 'next/headers'; export default async function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { const session = await auth.api.getSession({ headers: await headers(), }); console.debug('RootLayout', { session }); return ( <html lang="en" suppressHydrationWarning> <body> <Providers>{children}</Providers> <Analytics /> </body> </html> ); } ``` ### Current vs. Expected behavior One would expect to see "RootLayout: { session: { ... } }" but instead, the session is null. I can see the session token in the requests: ![Image](https://github.com/user-attachments/assets/bc0fd419-0de8-460a-9189-d769c868293f) And requests to /api/auth/get-session return a valid session: ![Image](https://github.com/user-attachments/assets/2c8b73d2-0362-4264-ac7b-0e3912a765da) ### What version of Better Auth are you using? 1.2.5 ### Provide environment information ```bash - OS: MacOS - Browser: Chrome ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript export const auth = betterAuth({ basePath: '/auth', database: prismaAdapter(prisma, { provider: 'postgresql', }), plugins: [ emailOTP({ sendVerificationOTP, }), nextCookies(), expo(), ], socialProviders: { google: { clientId: process.env.GOOGLE_CLIENT_ID as string, clientSecret: process.env.GOOGLE_CLIENT_SECRET as string, }, }, user: { additionalFields: { role: { type: 'string', required: false, defaultValue: 'user', input: false, }, lang: { type: 'string', required: false, defaultValue: 'en', }, }, }, }); ``` ### Additional context _No response_
GiteaMirror added the bug label 2026-03-13 08:11:07 -05:00
Author
Owner

@BjoernRave commented on GitHub (Mar 30, 2025):

I have the same issue when trying to retrieve the session inside the getRequestConfig fn of next-intl to retrieve the language of the user, which is also executed in the layout

@BjoernRave commented on GitHub (Mar 30, 2025): I have the same issue when trying to retrieve the session inside the `getRequestConfig` fn of next-intl to retrieve the language of the user, which is also executed in the layout
Author
Owner

@Kinfe123 commented on GitHub (Mar 30, 2025):

is it because you used it with in a layout file ? or does it persist with in other RSC's ?

@Kinfe123 commented on GitHub (Mar 30, 2025): is it because you used it with in a layout file ? or does it persist with in other RSC's ?
Author
Owner

@krzkz94 commented on GitHub (Mar 30, 2025):

@Kinfe123 also happens in a page component, not strictly related to layours

// page.tsx
export default async function WatchPage() {
    const session = await auth.api.getSession({
        headers: await headers()
    })
 
    console.log('better auth session', session);

    return <div>WatchPage { JSON.stringify(session) || 'no session' }</div>;
}

Session is null, cookie is present :)

@krzkz94 commented on GitHub (Mar 30, 2025): @Kinfe123 also happens in a page component, not strictly related to layours ``` // page.tsx export default async function WatchPage() { const session = await auth.api.getSession({ headers: await headers() }) console.log('better auth session', session); return <div>WatchPage { JSON.stringify(session) || 'no session' }</div>; } ``` Session is null, cookie is present :)
Author
Owner

@Kinfe123 commented on GitHub (Mar 30, 2025):

Image

i have upgraded the version to 1.2.5 and try to repro it on both but it is working fine .. may be can u pls check if the cookies is being stale or some other services or even using multiple apps are overriding the value and making it invalid so can you try cleaning it up and try it again if that works.

@Kinfe123 commented on GitHub (Mar 30, 2025): <img width="288" alt="Image" src="https://github.com/user-attachments/assets/92a369ec-1a49-4b88-9b81-efcf00cf3d43" /> i have upgraded the version to 1.2.5 and try to repro it on both but it is working fine .. may be can u pls check if the cookies is being stale or some other services or even using multiple apps are overriding the value and making it invalid so can you try cleaning it up and try it again if that works.
Author
Owner

@krzkz94 commented on GitHub (Mar 30, 2025):

Hey! Attached some extra info below

code

console.log('headers', JSON.stringify(await headers()));
    console.log('cookies', JSON.stringify(await cookies()));

    const authSession = await auth.api.getSession({
        headers: await headers(),
    });

    console.log('better auth session', authSession);

await headers()

{"headers":{"host":"localhost:3000","connection":"keep-alive","pragma":"no-cache","cache-control":"no-cache","sec-ch-ua":"\"Chromium\";v=\"134\", \"Not:A-Brand\";v=\"24\", \"Google Chrome\";v=\"134\"","sec-ch-ua-mobile":"?0","sec-ch-ua-platform":"\"macOS\"","upgrade-insecure-requests":"1","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7","sec-fetch-site":"same-origin","sec-fetch-mode":"navigate","sec-fetch-dest":"document","referer":"http://localhost:3000/watch/xxx","accept-encoding":"gzip, deflate, br, zstd","accept-language":"en-US,en;q=0.9","cookie":"__next_hmr_refresh_hash__=38; better-auth.session_token=OvLl8X4XAGOvjBBrasKH4TgyuDAHONFR.OZ%2FATHQIda5ZSzY2gIn9AtMEtrBkQ027c2GkPFbY75k%3D","x-forwarded-host":"localhost:3000","x-forwarded-port":"3000","x-forwarded-proto":"http","x-forwarded-for":"::1"}}

await cookies()

 {"_parsed":{},"_headers":{"headers":{"host":"localhost:3000","connection":"keep-alive","pragma":"no-cache","cache-control":"no-cache","sec-ch-ua":"\"Chromium\";v=\"134\", \"Not:A-Brand\";v=\"24\", \"Google Chrome\";v=\"134\"","sec-ch-ua-mobile":"?0","sec-ch-ua-platform":"\"macOS\"","upgrade-insecure-requests":"1","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7","sec-fetch-site":"same-origin","sec-fetch-mode":"navigate","sec-fetch-dest":"document","referer":"http://localhost:3000/watch/xxx","accept-encoding":"gzip, deflate, br, zstd","accept-language":"en-US,en;q=0.9","cookie":"__next_hmr_refresh_hash__=38; better-auth.session_token=OvLl8X4XAGOvjBBrasKH4TgyuDAHONFR.OZ%2FATHQIda5ZSzY2gIn9AtMEtrBkQ027c2GkPFbY75k%3D","x-forwarded-host":"localhost:3000","x-forwarded-port":"3000","x-forwarded-proto":"http","x-forwarded-for":"::1"}}}

better auth session null

NextJS 15.2.4
better-auth: 1.2.0, 1.2.4, 1.2.5 (Tried all 3, downgrading both on server / client)

Then just after the code to get it trough the better-auth API I got a http call

export const getSessionQuery = async ({ cookies }: { cookies: string }) => {
    const { data: session } = await betterFetch<Session>("/auth/get-session", {
        baseURL: `${process.env.NEXT_PUBLIC_API_URL}`,
        headers: {
            cookie: cookies, // Forward the cookies from the request
        },
    });

    return session;
}

export const getSession = async () => {
    return getSessionQuery({ cookies: (await cookies()).toString() });
}

const session = await getSession();

console.log('better auth session2', session);
better auth session2 {
  session: {
    id: '3iWNFcz0NVgVvwFQN9gPAjpviygqVXMm',
    expiresAt: '2025-04-06T11:47:13.321Z',
    token: 'OvLl8X4XAGOvjBBrasKH4TgyuDAHONFR',
    createdAt: '2025-03-30T11:47:13.321Z',
    updatedAt: '2025-03-30T11:47:13.321Z',
    ipAddress: '::1',
    userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36',
    userId: 'oKK3kT38oYhjCdlrdX5UqozWSuk640XV'
  },
  user: {
    id: 'oKK3kT38oYhjCdlrdX5UqozWSuk640XV',
    name: '',
    email: 'xxx@gmail.com',
    emailVerified: true,
    image: null,
    createdAt: '2025-03-30T10:54:44.112Z',
    updatedAt: '2025-03-30T10:54:44.112Z'
  }
}

All this was in the same "request" with the same cookies and headers FYI

@krzkz94 commented on GitHub (Mar 30, 2025): Hey! Attached some extra info below code ``` console.log('headers', JSON.stringify(await headers())); console.log('cookies', JSON.stringify(await cookies())); const authSession = await auth.api.getSession({ headers: await headers(), }); console.log('better auth session', authSession); ``` await headers() ``` {"headers":{"host":"localhost:3000","connection":"keep-alive","pragma":"no-cache","cache-control":"no-cache","sec-ch-ua":"\"Chromium\";v=\"134\", \"Not:A-Brand\";v=\"24\", \"Google Chrome\";v=\"134\"","sec-ch-ua-mobile":"?0","sec-ch-ua-platform":"\"macOS\"","upgrade-insecure-requests":"1","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7","sec-fetch-site":"same-origin","sec-fetch-mode":"navigate","sec-fetch-dest":"document","referer":"http://localhost:3000/watch/xxx","accept-encoding":"gzip, deflate, br, zstd","accept-language":"en-US,en;q=0.9","cookie":"__next_hmr_refresh_hash__=38; better-auth.session_token=OvLl8X4XAGOvjBBrasKH4TgyuDAHONFR.OZ%2FATHQIda5ZSzY2gIn9AtMEtrBkQ027c2GkPFbY75k%3D","x-forwarded-host":"localhost:3000","x-forwarded-port":"3000","x-forwarded-proto":"http","x-forwarded-for":"::1"}} ``` await cookies() ``` {"_parsed":{},"_headers":{"headers":{"host":"localhost:3000","connection":"keep-alive","pragma":"no-cache","cache-control":"no-cache","sec-ch-ua":"\"Chromium\";v=\"134\", \"Not:A-Brand\";v=\"24\", \"Google Chrome\";v=\"134\"","sec-ch-ua-mobile":"?0","sec-ch-ua-platform":"\"macOS\"","upgrade-insecure-requests":"1","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7","sec-fetch-site":"same-origin","sec-fetch-mode":"navigate","sec-fetch-dest":"document","referer":"http://localhost:3000/watch/xxx","accept-encoding":"gzip, deflate, br, zstd","accept-language":"en-US,en;q=0.9","cookie":"__next_hmr_refresh_hash__=38; better-auth.session_token=OvLl8X4XAGOvjBBrasKH4TgyuDAHONFR.OZ%2FATHQIda5ZSzY2gIn9AtMEtrBkQ027c2GkPFbY75k%3D","x-forwarded-host":"localhost:3000","x-forwarded-port":"3000","x-forwarded-proto":"http","x-forwarded-for":"::1"}}} ``` better auth session null NextJS 15.2.4 better-auth: 1.2.0, 1.2.4, 1.2.5 (Tried all 3, downgrading both on server / client) Then just after the code to get it trough the better-auth API I got a http call ``` export const getSessionQuery = async ({ cookies }: { cookies: string }) => { const { data: session } = await betterFetch<Session>("/auth/get-session", { baseURL: `${process.env.NEXT_PUBLIC_API_URL}`, headers: { cookie: cookies, // Forward the cookies from the request }, }); return session; } export const getSession = async () => { return getSessionQuery({ cookies: (await cookies()).toString() }); } const session = await getSession(); console.log('better auth session2', session); ``` ``` better auth session2 { session: { id: '3iWNFcz0NVgVvwFQN9gPAjpviygqVXMm', expiresAt: '2025-04-06T11:47:13.321Z', token: 'OvLl8X4XAGOvjBBrasKH4TgyuDAHONFR', createdAt: '2025-03-30T11:47:13.321Z', updatedAt: '2025-03-30T11:47:13.321Z', ipAddress: '::1', userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36', userId: 'oKK3kT38oYhjCdlrdX5UqozWSuk640XV' }, user: { id: 'oKK3kT38oYhjCdlrdX5UqozWSuk640XV', name: '', email: 'xxx@gmail.com', emailVerified: true, image: null, createdAt: '2025-03-30T10:54:44.112Z', updatedAt: '2025-03-30T10:54:44.112Z' } } ``` All this was in the same "request" with the same cookies and headers FYI
Author
Owner

@Kinfe123 commented on GitHub (Mar 30, 2025):

hmm for auth.api.getSession() which is like a handler that we run as function instead of calling endpoint which the client hooks does but as i said this is sth that other developer are using it for most of the usecase for fetching the user and session and it should have probably been asked by many developer. i mean i dont think there is a bug here but also might be an edge on some conflicting things. ig it should be somewhere in your causing an issue since the route is already mounted as you mentioned. may be on your end try to clean up stuff or restart servers or other thing that is related to your auth as well but lets open it if others do have the problem as well...

@Kinfe123 commented on GitHub (Mar 30, 2025): hmm for auth.api.getSession() which is like a handler that we run as function instead of calling endpoint which the client hooks does but as i said this is sth that other developer are using it for most of the usecase for fetching the user and session and it should have probably been asked by many developer. i mean i dont think there is a bug here but also might be an edge on some conflicting things. ig it should be somewhere in your causing an issue since the route is already mounted as you mentioned. may be on your end try to clean up stuff or restart servers or other thing that is related to your auth as well but lets open it if others do have the problem as well...
Author
Owner

@Kinfe123 commented on GitHub (Mar 30, 2025):

I have the same issue when trying to retrieve the session inside the getRequestConfig fn of next-intl to retrieve the language of the user, which is also executed in the layout

wait does it work before adding it ?

@Kinfe123 commented on GitHub (Mar 30, 2025): > I have the same issue when trying to retrieve the session inside the `getRequestConfig` fn of next-intl to retrieve the language of the user, which is also executed in the layout wait does it work before adding it ?
Author
Owner

@BjoernRave commented on GitHub (Mar 30, 2025):

before adding what? next-intl works fine without adding the getSession call inside it or what do you mean exactly?

@BjoernRave commented on GitHub (Mar 30, 2025): before adding what? next-intl works fine without adding the getSession call inside it or what do you mean exactly?
Author
Owner

@ian commented on GitHub (Mar 30, 2025):

I can't even get the /auth/get-session to return a session when I construct a fetch call manually from the server with cookies forwarded.

Is there some way to turn on debugging to see what's happening at this endpoint, and why it's getting rejected?

@ian commented on GitHub (Mar 30, 2025): I can't even get the /auth/get-session to return a session when I construct a fetch call manually from the server with cookies forwarded. Is there some way to turn on debugging to see what's happening at this endpoint, and why it's getting rejected?
Author
Owner

@Kinfe123 commented on GitHub (Mar 30, 2025):

before adding what? next-intl works fine without adding the getSession call inside it or what do you mean exactly?

i mean before adding next-intl and additionalFields.

@Kinfe123 commented on GitHub (Mar 30, 2025): > before adding what? next-intl works fine without adding the getSession call inside it or what do you mean exactly? i mean before adding next-intl and additionalFields.
Author
Owner

@BjoernRave commented on GitHub (Mar 30, 2025):

ahh, in general better-auth works fine for me. I added it to an existing application so next-intl was already there. My only issue was getting the session inside the getRequestConfig call, which is (I am 95% certain) done on the server, so related to the issue. Btw. this is my core, I use the customSession plugin:

import { prisma } from "@scoutello/db"
import { sendMail } from "@scoutello/mail"
import { getLanguages } from "@scoutello/shared/constants"
import { userSelect } from "@scoutello/shared/includes"
import { trustedOrigins } from "@scoutello/shared/trusted-origins"
import { getFullUrl } from "@scoutello/shared/utils"
import acceptLanguageParser from "accept-language-parser"
import { betterAuth } from "better-auth"
import { prismaAdapter } from "better-auth/adapters/prisma"
import {
  anonymous,
  createAuthMiddleware,
  customSession,
  emailOTP,
} from "better-auth/plugins"

const formatUser = (user) => ({
  ...user,
  images: user.images
    .sort((a, b) => a.order - b.order)
    .map((i) => ({
      ...i,
      image: {
        ...i.image,
        fullUrl: getFullUrl(i.image.url),
      },
    })),
  description: user?.descriptions?.find((d) => d.language === user.language)
    ?.text,
  organizations: user.organizations.map((p) => ({
    ...p.organization,
    permissions: p.permissions.split(","),
  })),
  email: user.email,
  guideInTours: user.guideInTours,
})

export const auth = betterAuth({
  appName: "Scoutello",
  database: prismaAdapter(prisma, {
    provider: "postgresql",
  }),
  account: {
    accountLinking: {
      trustedProviders: ["google", "apple", "linkedin"],
    },
  },
  emailAndPassword: {
    enabled: true,
  },
  socialProviders: {
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID || "",
      clientSecret: process.env.GOOGLE_CLIENT_SECRET || "",
      redirectURI: `${process.env.NEXT_PUBLIC_DASHBOARD_URL}/api/auth/callback/google`,
      mapProfileToUser: async (profile) => {
        console.log(profile, "goggle")

        return {
          email: profile.email,
          firstName: profile.given_name,
          lastName: profile.family_name,
        }
      },
    },
    apple: {
      clientId: process.env.APPLE_CLIENT_ID || "",
      clientSecret: process.env.APPLE_CLIENT_SECRET || "",
      redirectURI: `${process.env.NEXT_PUBLIC_DASHBOARD_URL}/api/auth/callback/apple`,
      mapProfileToUser: async (profile) => {
        console.log(profile, "apple")

        return {
          email: profile.email,
        }
      },
    },
    linkedin: {
      clientId: process.env.LINKEDIN_CLIENT_ID || "",
      clientSecret: process.env.LINKEDIN_CLIENT_SECRET || "",
      redirectURI: `${process.env.NEXT_PUBLIC_DASHBOARD_URL}/api/auth/callback/linkedin`,
      mapProfileToUser: async (profile) => {
        console.log(profile, "linkedin")

        return {
          email: profile.email,
        }
      },
    },
  },
  trustedOrigins: trustedOrigins,
  hooks: {
    after: createAuthMiddleware(async (ctx) => {
      if (ctx.path?.includes("/sign-in/anonymous")) {
        const language = acceptLanguageParser.pick(
          getLanguages.map((l) => l.value),
          ctx.headers.get("accept-language"),
          {
            loose: true,
          },
        )

        await prisma.user.update({
          where: {
            id: (ctx.context.returned as any).user.id,
          },
          data: {
            language,
          },
        })
      }
    }),
  },
  plugins: [
    customSession(async ({ user, session }) => {
      const richUser = await prisma.user.findUnique({
        where: {
          id: user.id,
        },
        select: userSelect,
      })

      return {
        session,
        user: formatUser(richUser),
      }
    }),
    emailOTP({
      async sendVerificationOTP({ email, otp, type }) {
        await sendMail({
          to: email,
          type: "send-otp",
          variables: {
            otp,
            username: email,
          },
          language: "de",
        })
      },
    }),
    anonymous(),
  ],
})
@BjoernRave commented on GitHub (Mar 30, 2025): ahh, in general better-auth works fine for me. I added it to an existing application so next-intl was already there. My only issue was getting the session inside the getRequestConfig call, which is (I am 95% certain) done on the server, so related to the issue. Btw. this is my core, I use the customSession plugin: ```typescript import { prisma } from "@scoutello/db" import { sendMail } from "@scoutello/mail" import { getLanguages } from "@scoutello/shared/constants" import { userSelect } from "@scoutello/shared/includes" import { trustedOrigins } from "@scoutello/shared/trusted-origins" import { getFullUrl } from "@scoutello/shared/utils" import acceptLanguageParser from "accept-language-parser" import { betterAuth } from "better-auth" import { prismaAdapter } from "better-auth/adapters/prisma" import { anonymous, createAuthMiddleware, customSession, emailOTP, } from "better-auth/plugins" const formatUser = (user) => ({ ...user, images: user.images .sort((a, b) => a.order - b.order) .map((i) => ({ ...i, image: { ...i.image, fullUrl: getFullUrl(i.image.url), }, })), description: user?.descriptions?.find((d) => d.language === user.language) ?.text, organizations: user.organizations.map((p) => ({ ...p.organization, permissions: p.permissions.split(","), })), email: user.email, guideInTours: user.guideInTours, }) export const auth = betterAuth({ appName: "Scoutello", database: prismaAdapter(prisma, { provider: "postgresql", }), account: { accountLinking: { trustedProviders: ["google", "apple", "linkedin"], }, }, emailAndPassword: { enabled: true, }, socialProviders: { google: { clientId: process.env.GOOGLE_CLIENT_ID || "", clientSecret: process.env.GOOGLE_CLIENT_SECRET || "", redirectURI: `${process.env.NEXT_PUBLIC_DASHBOARD_URL}/api/auth/callback/google`, mapProfileToUser: async (profile) => { console.log(profile, "goggle") return { email: profile.email, firstName: profile.given_name, lastName: profile.family_name, } }, }, apple: { clientId: process.env.APPLE_CLIENT_ID || "", clientSecret: process.env.APPLE_CLIENT_SECRET || "", redirectURI: `${process.env.NEXT_PUBLIC_DASHBOARD_URL}/api/auth/callback/apple`, mapProfileToUser: async (profile) => { console.log(profile, "apple") return { email: profile.email, } }, }, linkedin: { clientId: process.env.LINKEDIN_CLIENT_ID || "", clientSecret: process.env.LINKEDIN_CLIENT_SECRET || "", redirectURI: `${process.env.NEXT_PUBLIC_DASHBOARD_URL}/api/auth/callback/linkedin`, mapProfileToUser: async (profile) => { console.log(profile, "linkedin") return { email: profile.email, } }, }, }, trustedOrigins: trustedOrigins, hooks: { after: createAuthMiddleware(async (ctx) => { if (ctx.path?.includes("/sign-in/anonymous")) { const language = acceptLanguageParser.pick( getLanguages.map((l) => l.value), ctx.headers.get("accept-language"), { loose: true, }, ) await prisma.user.update({ where: { id: (ctx.context.returned as any).user.id, }, data: { language, }, }) } }), }, plugins: [ customSession(async ({ user, session }) => { const richUser = await prisma.user.findUnique({ where: { id: user.id, }, select: userSelect, }) return { session, user: formatUser(richUser), } }), emailOTP({ async sendVerificationOTP({ email, otp, type }) { await sendMail({ to: email, type: "send-otp", variables: { otp, username: email, }, language: "de", }) }, }), anonymous(), ], }) ```
Author
Owner

@ian commented on GitHub (Mar 30, 2025):

@BjoernRave this is not a next-intl issue, there are some strange behaviors with the get-session endpoint. Sometimes it refuses to return a response body but includes a 200 status.

@ian commented on GitHub (Mar 30, 2025): @BjoernRave this is not a next-intl issue, there are some strange behaviors with the get-session endpoint. Sometimes it refuses to return a response body but includes a 200 status.
Author
Owner

@ian commented on GitHub (Mar 30, 2025):

I've found that I can make the /auth/get-session call manually and it works fine, it's just when using the auth.api.getSession helper it doesn't work at all.

Layout:

export default async function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  const { user } = await withAuth();

  console.debug('RootLayout', { user });

  return (
    <html lang="en" suppressHydrationWarning>
      <body
        className={cn(
          fontSans.variable,
          fontMono.variable,
          fontSerif.variable,
          'antialiased',
        )}
      >
        <Providers user={user}>{children}</Providers>
        <Analytics />
      </body>
    </html>
  );
}

WORKING:

export const withAuth = async () => {
  const headersList = await headers();
  const cookie = headersList.get('cookie');

  const session = await fetch(getWebUrl('/auth/get-session'), {
    headers: {
      'Content-Type': 'application/json',
      cookie: cookie ?? '',
    },
  }).then((res) => res.json());

  return session ?? { user: null, session: null };
};

DOES NOT WORK:

export const withAuth = async () => {
  const session = await auth.api.getSession({
    headers: await headers(),
  });

  return session ?? { user: null, session: null };
};
@ian commented on GitHub (Mar 30, 2025): I've found that I can make the /auth/get-session call manually and it works fine, it's just when using the auth.api.getSession helper it doesn't work at all. Layout: ```ts export default async function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { const { user } = await withAuth(); console.debug('RootLayout', { user }); return ( <html lang="en" suppressHydrationWarning> <body className={cn( fontSans.variable, fontMono.variable, fontSerif.variable, 'antialiased', )} > <Providers user={user}>{children}</Providers> <Analytics /> </body> </html> ); } ``` WORKING: ```ts export const withAuth = async () => { const headersList = await headers(); const cookie = headersList.get('cookie'); const session = await fetch(getWebUrl('/auth/get-session'), { headers: { 'Content-Type': 'application/json', cookie: cookie ?? '', }, }).then((res) => res.json()); return session ?? { user: null, session: null }; }; ``` DOES NOT WORK: ```ts export const withAuth = async () => { const session = await auth.api.getSession({ headers: await headers(), }); return session ?? { user: null, session: null }; }; ```
Author
Owner

@BjoernRave commented on GitHub (Mar 31, 2025):

this is how the response looks like: session { "data": null, "error": { "status": 0, "statusText": "" } }

@BjoernRave commented on GitHub (Mar 31, 2025): this is how the response looks like: ```session { "data": null, "error": { "status": 0, "statusText": "" } }```
Author
Owner

@serv commented on GitHub (Apr 1, 2025):

I'm facing the same issue.

One thing I am noticing is that the session is populated on the serverside when I am opening a page that use client.

But when the page doesn't have that, this issue happens and session is null for me. Not sure why this is the case.

@serv commented on GitHub (Apr 1, 2025): I'm facing the same issue. One thing I am noticing is that the session is populated on the serverside when I am opening a page that `use client`. But when the page doesn't have that, this issue happens and session is null for me. Not sure why this is the case.
Author
Owner

@ian commented on GitHub (Apr 1, 2025):

Have added better-auth to second application and it's the same exact problem.

@ian commented on GitHub (Apr 1, 2025): Have added better-auth to second application and it's the same exact problem.
Author
Owner

@Kinfe123 commented on GitHub (Apr 1, 2025):

@ian can you please send us the code sandbox or github link for more clarified reproduction

@Kinfe123 commented on GitHub (Apr 1, 2025): @ian can you please send us the code sandbox or github link for more clarified reproduction
Author
Owner

@soyricardodev commented on GitHub (Apr 8, 2025):

i had this issue with next canary and better-auth, from 1.2.3 and now with 1.2.5, for me doesnt work the manual fetch to /api/auth/get-session, my solution was to create a "server redirect", basically just a server action that i call when register, login or signout with the authClient helper, if i do a route.push("/another-page"), this dont "refetch" the session on the layout, but if i redirect from a server action this is working

i need the authClient because i like the onError and onSucces for toast stuff and logging, so i dont want to login from a server action 100%, so i just create that util called redirect.ts

// lib/redirect.ts
"use server";

import { redirect } from "next/navigation";

async function serverRedirect(url: string) {
	redirect(url);
}

export { serverRedirect };

And this is how i use it:

export function SignIn({ redirectTo }: SignInProps) {
  const form = useForm<SignInSchemaInput>({
    defaultValues: {
	email: "",
	password: "",
    },
	resolver: zodResolver(signInSchema),
	});

	const [isLoading, setLoading] = useState(false);

	const router = useRouter();

	async function onSubmit(data: SignInSchemaInput) {
		setLoading(true);
		try {
			await signIn.email({
				...data,
				fetchOptions: {
					onSuccess: () => {
                                              // Here is the magic
						serverRedirect(redirectTo ?? "/cursos");
					},
					onError: (e) => {
						if (e.error.code === "INVALID_EMAIL_OR_PASSWORD") {
							form.setError("email", { type: "custom", message: "" });
							form.setError("password", {
								type: "custom",
								message: "Correo o contraseña incorrectos",
							});
						}
						toast.error("Ha ocurrido un error");
					},
				},
			});
		} catch (error) {
			console.error(error);
		} finally {
			setLoading(false);
		}
	}
// More code...
@soyricardodev commented on GitHub (Apr 8, 2025): i had this issue with next canary and better-auth, from 1.2.3 and now with 1.2.5, for me doesnt work the manual fetch to /api/auth/get-session, my solution was to create a "server redirect", basically just a server action that i call when register, login or signout with the authClient helper, if i do a route.push("/another-page"), this dont "refetch" the session on the layout, but if i redirect from a server action this is working i need the authClient because i like the onError and onSucces for toast stuff and logging, so i dont want to login from a server action 100%, so i just create that util called redirect.ts ``` // lib/redirect.ts "use server"; import { redirect } from "next/navigation"; async function serverRedirect(url: string) { redirect(url); } export { serverRedirect }; ``` And this is how i use it: ``` export function SignIn({ redirectTo }: SignInProps) { const form = useForm<SignInSchemaInput>({ defaultValues: { email: "", password: "", }, resolver: zodResolver(signInSchema), }); const [isLoading, setLoading] = useState(false); const router = useRouter(); async function onSubmit(data: SignInSchemaInput) { setLoading(true); try { await signIn.email({ ...data, fetchOptions: { onSuccess: () => { // Here is the magic serverRedirect(redirectTo ?? "/cursos"); }, onError: (e) => { if (e.error.code === "INVALID_EMAIL_OR_PASSWORD") { form.setError("email", { type: "custom", message: "" }); form.setError("password", { type: "custom", message: "Correo o contraseña incorrectos", }); } toast.error("Ha ocurrido un error"); }, }, }); } catch (error) { console.error(error); } finally { setLoading(false); } } // More code... ```
Author
Owner

@Bekacru commented on GitHub (Apr 11, 2025):

can anyone share me a POC? I couldn't reproduce it either and this is a very important issue to address

@Bekacru commented on GitHub (Apr 11, 2025): can anyone share me a POC? I couldn't reproduce it either and this is a very important issue to address
Author
Owner

@soyricardodev commented on GitHub (Apr 11, 2025):

can anyone share me a POC? I couldn't reproduce it either and this is a very important issue to address

I could do it, I'd love to. But one question, once I do it, how can I let you know? Would it work for you here?

@soyricardodev commented on GitHub (Apr 11, 2025): > can anyone share me a POC? I couldn't reproduce it either and this is a very important issue to address I could do it, I'd love to. But one question, once I do it, how can I let you know? Would it work for you here?
Author
Owner

@Bekacru commented on GitHub (Apr 11, 2025):

@soyricardodev yes. make the repo public and share the link in this thread.

@Bekacru commented on GitHub (Apr 11, 2025): @soyricardodev yes. make the repo public and share the link in this thread.
Author
Owner

@capaj commented on GitHub (Apr 15, 2025):

same problem here @ian your solution with calling the API with fetch works. Definitely a bug and pretty frustrating one.
I am on 1.2.7.

here's my code snippet including the proper types for the session:

  // TODO use auth.api.getSession when https://github.com/better-auth/better-auth/issues/2055 is fixed
  const session = await fetch(
    `${process.env.VERCEL_URL}/api/auth/get-session`,
    {
      headers: {
        'Content-Type': 'application/json',
        cookie: cookie ?? ''
      }
    }
  ).then((res) => res.json() as ReturnType<typeof auth.api.getSession>)
@capaj commented on GitHub (Apr 15, 2025): same problem here @ian your solution with calling the API with fetch works. Definitely a bug and pretty frustrating one. I am on 1.2.7. here's my code snippet including the proper types for the session: ```ts // TODO use auth.api.getSession when https://github.com/better-auth/better-auth/issues/2055 is fixed const session = await fetch( `${process.env.VERCEL_URL}/api/auth/get-session`, { headers: { 'Content-Type': 'application/json', cookie: cookie ?? '' } } ).then((res) => res.json() as ReturnType<typeof auth.api.getSession>) ```
Author
Owner

@moreorover commented on GitHub (Apr 16, 2025):

I was not able to reproduce this exact problem, session always logs for me as it should inside root /src/app/layout.ts

However, I have found a very similar issue but with tRPC. After refreshing page first request that goes to private procedure comes out as unauthorized because session object received by tRPC is null.

Here is reproduction:
https://github.com/moreorover/prive-video/tree/reproduction

Instructions to start the project are found at https://github.com/moreorover/prive-video/blob/reproduction/README.md

@moreorover commented on GitHub (Apr 16, 2025): I was not able to reproduce this exact problem, session always logs for me as it should inside root `/src/app/layout.ts` However, I have found a very similar issue but with tRPC. After refreshing page first request that goes to private procedure comes out as unauthorized because session object received by tRPC is null. Here is reproduction: https://github.com/moreorover/prive-video/tree/reproduction Instructions to start the project are found at https://github.com/moreorover/prive-video/blob/reproduction/README.md
Author
Owner

@soyricardodev commented on GitHub (Apr 17, 2025):

@soyricardodev yes. make the repo public and share the link in this thread.

Repo to reproduce here: https://github.com/soyricardodev/better-auth-nextjs-session-bug

Also a video

https://github.com/user-attachments/assets/93bf3cde-d237-451f-987c-1e94f04cda80

@soyricardodev commented on GitHub (Apr 17, 2025): > [@soyricardodev](https://github.com/soyricardodev) yes. make the repo public and share the link in this thread. [Repo to reproduce here: https://github.com/soyricardodev/better-auth-nextjs-session-bug](https://github.com/soyricardodev/better-auth-nextjs-session-bug) Also a video https://github.com/user-attachments/assets/93bf3cde-d237-451f-987c-1e94f04cda80
Author
Owner

@soyricardodev commented on GitHub (Apr 17, 2025):

@soyricardodev yes. make the repo public and share the link in this thread.

Repo to reproduce here: https://github.com/soyricardodev/better-auth-nextjs-session-bug

Also a video

Better.Auth.nextjs.bug.webm

@Bekacru if you need more details, or help to reproduce feel free to lmk

i am very insterested to make this work by default as it should, better-auth is awesome

@soyricardodev commented on GitHub (Apr 17, 2025): > > [@soyricardodev](https://github.com/soyricardodev) yes. make the repo public and share the link in this thread. > > [Repo to reproduce here: https://github.com/soyricardodev/better-auth-nextjs-session-bug](https://github.com/soyricardodev/better-auth-nextjs-session-bug) > > Also a video > > Better.Auth.nextjs.bug.webm @Bekacru if you need more details, or help to reproduce feel free to lmk i am very insterested to make this work by default as it should, better-auth is awesome
Author
Owner

@drago1520 commented on GitHub (Apr 19, 2025):

I have the same issue here. Again, such a basic feature is missing: the ability to simply get the session from an anonymous user.

@drago1520 commented on GitHub (Apr 19, 2025): I have the same issue here. Again, such a basic feature is missing: the ability to simply get the session from an anonymous user.
Author
Owner

@Joe-Taka commented on GitHub (Apr 20, 2025):

For some reason /api/auth/get-session returns null for me, which also happens for auth.api.getSession(...).

@Joe-Taka commented on GitHub (Apr 20, 2025): For some reason `/api/auth/get-session` returns null for me, which also happens for `auth.api.getSession(...)`.
Author
Owner

@soyricardodev commented on GitHub (Apr 21, 2025):

For some reason /api/auth/get-session returns null for me, which also happens for auth.api.getSession(...).

in which cases do you have that issue, can you share some code and your use?

@soyricardodev commented on GitHub (Apr 21, 2025): > For some reason `/api/auth/get-session` returns null for me, which also happens for `auth.api.getSession(...)`. in which cases do you have that issue, can you share some code and your use?
Author
Owner

@soyricardodev commented on GitHub (Apr 21, 2025):

For some reason /api/auth/get-session returns null for me, which also happens for auth.api.getSession(...).

i didnt tested it with anon stuff, can you share a repro?

@soyricardodev commented on GitHub (Apr 21, 2025): > For some reason `/api/auth/get-session` returns null for me, which also happens for `auth.api.getSession(...)`. i didnt tested it with anon stuff, can you share a repro?
Author
Owner

@drago1520 commented on GitHub (Apr 25, 2025):

I am pretty sure

const user = await auth.api.signInAnonymous({headers: await headers()})

does not update the browser. Next.js 15.30

@drago1520 commented on GitHub (Apr 25, 2025): I am pretty sure ```js const user = await auth.api.signInAnonymous({headers: await headers()}) ``` does not update the browser. Next.js 15.30
Author
Owner

@drago1520 commented on GitHub (Apr 26, 2025):

I understood why this happens. You cannot send cookies from server components (as pointed out in #2434 ), so the browser is out of sync with the database sessions. You must use client components or server actions. Let's close this issue.

Image

@drago1520 commented on GitHub (Apr 26, 2025): I understood why this happens. You cannot send cookies from server components (as pointed out in #2434 ), so the browser is out of sync with the database sessions. You must use client components or server actions. Let's close this issue. ![Image](https://github.com/user-attachments/assets/f9ce838e-ef77-4c88-8653-e5b1a6560bd1)
Author
Owner

@BjoernRave commented on GitHub (Apr 26, 2025):

@drago1520 can you please open a seperate issue for your problem with anonymous session and not pollute this thread?

@BjoernRave commented on GitHub (Apr 26, 2025): @drago1520 can you please open a seperate issue for your problem with anonymous session and not pollute this thread?
Author
Owner

@drago1520 commented on GitHub (Apr 26, 2025):

@drago1520 can you please open a seperate issue for your problem with anonymous session and not pollute this thread?

I believe the issue is the same. We are trying to sign in from an RSC that does not support the writing of cookies. Thus, the browser does not return a session cookie, and we log null. Please let me know if I am wrong. More details at #2434

@drago1520 commented on GitHub (Apr 26, 2025): > [@drago1520](https://github.com/drago1520) can you please open a seperate issue for your problem with anonymous session and not pollute this thread? I believe the issue is the same. We are trying to sign in from an RSC that does not support the writing of cookies. Thus, the browser does not return a session cookie, and we log `null`. Please let me know if I am wrong. More details at #2434
Author
Owner

@soyricardodev commented on GitHub (Apr 26, 2025):

I understood why this happens. You cannot send cookies from server components (as pointed out in #2434 ), so the browser is out of sync with the database sessions. You must use client components or server actions. Let's close this issue.

Image

Can you elaborate more why this should be closed?

This happens even with client side stuff, if you see the examples from official docs and from this issue, we are using signIn from auth-client, this sets cookies and log the user with the auth handler, the cookies are being set, but the redirect with use router don't rfresh the browser UI data

@soyricardodev commented on GitHub (Apr 26, 2025): > I understood why this happens. You cannot send cookies from server components (as pointed out in [#2434](https://github.com/better-auth/better-auth/issues/2434) ), so the browser is out of sync with the database sessions. You must use client components or server actions. Let's close this issue. > > ![Image](https://github.com/user-attachments/assets/f9ce838e-ef77-4c88-8653-e5b1a6560bd1) Can you elaborate more why this should be closed? This happens even with client side stuff, if you see the examples from official docs and from this issue, we are using signIn from auth-client, this sets cookies and log the user with the auth handler, the cookies are being set, but the redirect with use router don't rfresh the browser UI data
Author
Owner

@Kinfe123 commented on GitHub (Apr 26, 2025):

@drago1520 but on the above mentioned threads, they were logging the headers and it does have the cookie and cant able to get the session but i see you are trying to run the action handler directly with the RSC.

@Kinfe123 commented on GitHub (Apr 26, 2025): @drago1520 but on the above mentioned threads, they were logging the headers and it does have the cookie and cant able to get the session but i see you are trying to run the action handler directly with the RSC.
Author
Owner

@edocollado commented on GitHub (May 7, 2025):

same problem here @ian your solution with calling the API with fetch works. Definitely a bug and pretty frustrating one. I am on 1.2.7.

here's my code snippet including the proper types for the session:

// TODO use auth.api.getSession when https://github.com/better-auth/better-auth/issues/2055 is fixed
const session = await fetch(
${process.env.VERCEL_URL}/api/auth/get-session,
{
headers: {
'Content-Type': 'application/json',
cookie: cookie ?? ''
}
}
).then((res) => res.json() as ReturnType)

i have the same problem

@edocollado commented on GitHub (May 7, 2025): > same problem here [@ian](https://github.com/ian) your solution with calling the API with fetch works. Definitely a bug and pretty frustrating one. I am on 1.2.7. > > here's my code snippet including the proper types for the session: > > // TODO use auth.api.getSession when https://github.com/better-auth/better-auth/issues/2055 is fixed > const session = await fetch( > `${process.env.VERCEL_URL}/api/auth/get-session`, > { > headers: { > 'Content-Type': 'application/json', > cookie: cookie ?? '' > } > } > ).then((res) => res.json() as ReturnType<typeof auth.api.getSession>) i have the same problem
Author
Owner

@ian commented on GitHub (May 7, 2025):

We're using a pnpm workspace with shared auth code, I wonder if it's related.

For those having issues, can you reply with whether you are using a package in a workspace, or as a standalone repo?

@ian commented on GitHub (May 7, 2025): We're using a pnpm workspace with shared auth code, I wonder if it's related. For those having issues, can you reply with whether you are using a package in a workspace, or as a standalone repo?
Author
Owner

@capaj commented on GitHub (May 7, 2025):

I am using pnpm in a monorepo

What do you mean by "shared Auth code"

@capaj commented on GitHub (May 7, 2025): I am using pnpm in a monorepo What do you mean by "shared Auth code"
Author
Owner

@aleehedl commented on GitHub (May 8, 2025):

I have the same issue, but only when I'm running in dev mode with turbopack: npx next dev --turbopack, which is the default for Next.js.

With production mode or even npx next dev it works.

@aleehedl commented on GitHub (May 8, 2025): I have the same issue, but only when I'm running in dev mode with turbopack: `npx next dev --turbopack`, which is the default for Next.js. With production mode or even `npx next dev` it **works**.
Author
Owner

@ricklabanca commented on GitHub (May 21, 2025):

I am glad I found this thread, it drives me crazy. In my server side code (a dto not related to a page directly) I get current user.
I can be running fine, and all of the sudden I have cookies but no session. Then a few minutes later it starts to work again. Restart makes no difference.

It is really strange because I don't see a pattern other than it stopping and suddenly start working again, same page just refreshing, nothing changes other than some time passing.

Are there some flags we could set for the session code? I am on the latest

@ricklabanca commented on GitHub (May 21, 2025): I am glad I found this thread, it drives me crazy. In my server side code (a dto not related to a page directly) I get current user. I can be running fine, and all of the sudden I have cookies but no session. Then a few minutes later it starts to work again. Restart makes no difference. It is really strange because I don't see a pattern other than it stopping and suddenly start working again, same page just refreshing, nothing changes other than some time passing. Are there some flags we could set for the session code? I am on the latest
Author
Owner

@Rieranthony commented on GitHub (May 21, 2025):

I have a similar issue, I have a setup with a monorepo.

Api in a Hono server with bun and Better auth
Web app with next js

Everything works fine, I get to do the social sign in with google, cookies are set, but const session = await auth.api.getSession({ headers: await headers(), });

Always returns null

Everything is on latest.

EDIT:
Getting the session client side wiht "useSession" works fine, so the setup works.

@Rieranthony commented on GitHub (May 21, 2025): I have a similar issue, I have a setup with a monorepo. > Api in a Hono server with bun and Better auth > Web app with next js Everything works fine, I get to do the social sign in with google, cookies are set, but `const session = await auth.api.getSession({ headers: await headers(), });` Always returns `null` Everything is on latest. EDIT: Getting the session client side wiht "useSession" works fine, so the setup works.
Author
Owner

@moreorover commented on GitHub (May 21, 2025):

I was not able to reproduce this exact problem, session always logs for me as it should inside root /src/app/layout.ts

However, I have found a very similar issue but with tRPC. After refreshing page first request that goes to private procedure comes out as unauthorized because session object received by tRPC is null.

Here is reproduction: https://github.com/moreorover/prive-video/tree/reproduction

Instructions to start the project are found at https://github.com/moreorover/prive-video/blob/reproduction/README.md

In my case this was due to the how Next.js handles cookies on server side. Here is the problem explained: https://github.com/t3-oss/create-t3-app/issues/1765

Nothing to do with Better Auth itself.

@moreorover commented on GitHub (May 21, 2025): > I was not able to reproduce this exact problem, session always logs for me as it should inside root `/src/app/layout.ts` > > However, I have found a very similar issue but with tRPC. After refreshing page first request that goes to private procedure comes out as unauthorized because session object received by tRPC is null. > > Here is reproduction: https://github.com/moreorover/prive-video/tree/reproduction > > Instructions to start the project are found at https://github.com/moreorover/prive-video/blob/reproduction/README.md In my case this was due to the how Next.js handles cookies on server side. Here is the problem explained: https://github.com/t3-oss/create-t3-app/issues/1765 Nothing to do with Better Auth itself.
Author
Owner

@dolanoadriano commented on GitHub (May 27, 2025):

I have the problems in the dev.
After building it works.

@dolanoadriano commented on GitHub (May 27, 2025): I have the problems in the **dev**. After building it works.
Author
Owner

@dolanoadriano commented on GitHub (May 27, 2025):

update: when I disable the --turbopack argument for the next dev script the problem disappears

@dolanoadriano commented on GitHub (May 27, 2025): update: when I disable the `--turbopack` argument for the `next dev` script the problem disappears
Author
Owner

@elpidev commented on GitHub (May 30, 2025):

I didn't run into this issue before, but it started happening about a week ago.
I have a lot of customizations, so I tried reverting to a minimal setup, but the issue still persists.

The user/session is fetched in the root layout and other pages, and if it's null, it redirects to the login page, which is causing users to be logged out frequently.

I added a query param to /login like /login?r=201 to help track where the redirect is coming from. In my case, it's not just triggered in the root layout, it also happens on other pages.

I'm wondering if there's any workaround available at the moment.

@elpidev commented on GitHub (May 30, 2025): I didn't run into this issue before, but it started happening about a week ago. I have a lot of customizations, so I tried reverting to a minimal setup, but the issue still persists. The user/session is fetched in the root layout and other pages, and if it's null, it redirects to the login page, which is causing users to be logged out frequently. I added a query param to `/login` like `/login?r=201` to help track where the redirect is coming from. In my case, it's not just triggered in the root layout, it also happens on other pages. I'm wondering if there's any workaround available at the moment.
Author
Owner

@binarytide commented on GitHub (Jun 4, 2025):

I'm trying to wrap better-auth in an Effect service, and calls like signInEmail successfully returns { redirect, token, user } no problem, but I can't get anything back from getSession

@binarytide commented on GitHub (Jun 4, 2025): I'm trying to wrap better-auth in an Effect service, and calls like signInEmail successfully returns { redirect, token, user } no problem, but I can't get anything back from getSession
Author
Owner

@binarytide commented on GitHub (Jun 4, 2025):

I'll gladly construct a simple poc if it's still needed

@binarytide commented on GitHub (Jun 4, 2025): I'll gladly construct a simple poc if it's still needed
Author
Owner

@Kinfe123 commented on GitHub (Jun 5, 2025):

Yeah would love that.

@Kinfe123 commented on GitHub (Jun 5, 2025): Yeah would love that.
Author
Owner

@Kinfe123 commented on GitHub (Jun 20, 2025):

@soyricardodev If you look closely, the server session is null before authentication, which makes sense. However, the session is not displayed as null after you click the signup button which means it is not being re-rendered for that unfulfilled or fulfilled promise.
Beyond that, it also seems like an architectural issue , there should be a state change in your context for triggering a re-render of the Nav component, even when you pass the hot promise created on the server.

@Kinfe123 commented on GitHub (Jun 20, 2025): @soyricardodev If you look closely, the server session is null before authentication, which makes sense. However, the session is not displayed as null after you click the signup button which means it is not being re-rendered for that unfulfilled or fulfilled promise. Beyond that, it also seems like an architectural issue , there should be a state change in your context for triggering a re-render of the Nav component, even when you pass the hot promise created on the server.
Author
Owner

@applicazza commented on GitHub (Jun 23, 2025):

I've managed to authenticate user anonymously with following code in React Router v7 root.tsx:

export async function loader({ request }: Route.LoaderArgs) {
  const { headers } = request;

  const session = await auth.api.getSession({ headers });

  if (!session) {
    const anonymous = await auth.api.signInAnonymous({
      returnHeaders: true,
    });

    return data(
      {},
      {
        ...(anonymous ? { headers: anonymous.headers } : {}),
      },
    );
  }

  return {};
}
@applicazza commented on GitHub (Jun 23, 2025): I've managed to authenticate user anonymously with following code in React Router v7 `root.tsx`: ```typescript export async function loader({ request }: Route.LoaderArgs) { const { headers } = request; const session = await auth.api.getSession({ headers }); if (!session) { const anonymous = await auth.api.signInAnonymous({ returnHeaders: true, }); return data( {}, { ...(anonymous ? { headers: anonymous.headers } : {}), }, ); } return {}; } ```
Author
Owner

@mateo-m commented on GitHub (Jun 24, 2025):

Removing the --turbopack flag when running my NextJS app in dev mode has "reduced" the occurence of the issue for me, but it still happens sometimes - I'm not sure why though, and it disables the recent optimizations that come with Turbopack 😥.

  • better-auth: v1.2.10
  • next: v15.3.0
@mateo-m commented on GitHub (Jun 24, 2025): Removing the `--turbopack` flag when running my NextJS app in dev mode has "reduced" the occurence of the issue for me, but it still happens sometimes - I'm not sure why though, and it disables the recent optimizations that come with Turbopack 😥. - `better-auth`: v1.2.10 - `next`: v15.3.0
Author
Owner

@quroneko-del commented on GitHub (Jun 25, 2025):

In my case, the issue was caused by the hono/language middleware. It seemed to overwrite the cookies after a successful sign-in, so the token couldn't be retained.

import { languageDetector } from 'hono/language'

app.use(
  languageDetector({
    caches: false // 👈 disable caching
  })
)

Disabling the cache like this resolved the issue.

@quroneko-del commented on GitHub (Jun 25, 2025): In my case, the issue was caused by the **hono/language** middleware. It seemed to overwrite the cookies after a successful sign-in, so the token couldn't be retained. ```typescript import { languageDetector } from 'hono/language' app.use( languageDetector({ caches: false // 👈 disable caching }) ) ``` Disabling the cache like this resolved the issue.
Author
Owner

@bcheung commented on GitHub (Jun 27, 2025):

Also experiencing something similar although I am making the request to my Hono API from the client side.

BUT, it randomly happens once in ~10-20 requests to the get-session endpoint.
When I inspect the requests, I can see that cookies are set properly, there is a valid session in the DB, but sometimes the response is null instead of returning the session data.

Cookies set:
Image

Valid non-expired session:
Image

Null response but status 200:
Image

And refreshing the page again often would result in a successful non-null response body:
Image

Until I refresh it for another 10-20 times then I get a null response.

I have a SPA Expo react native app running on web with better auth routes configured on my Hono API.
Using better auth 1.2.8

It's pretty hard to debug bc it randomly occurs pretty infrequently. But still a huge issue because my app redirects the user to log in again when this happens.
Let me know if anyone has any pointers on how I can debug this type of thing

@bcheung commented on GitHub (Jun 27, 2025): Also experiencing something similar although I am making the request to my Hono API from the client side. BUT, it randomly happens once in ~10-20 requests to the get-session endpoint. When I inspect the requests, I can see that cookies are set properly, there is a valid session in the DB, but sometimes the response is null instead of returning the session data. Cookies set: ![Image](https://github.com/user-attachments/assets/dc37fc70-0180-433b-9245-85a1c0aae23a) Valid non-expired session: ![Image](https://github.com/user-attachments/assets/a33fed97-351e-4908-a4f2-3e02d9e5aa40) Null response but status 200: ![Image](https://github.com/user-attachments/assets/b61440e9-eb91-4451-acde-89621c02cf36) And refreshing the page again often would result in a successful non-null response body: ![Image](https://github.com/user-attachments/assets/5c36496f-b923-44d4-8ca4-9731fbecf007) Until I refresh it for another 10-20 times then I get a null response. I have a SPA Expo react native app running on web with better auth routes configured on my Hono API. Using better auth 1.2.8 It's pretty hard to debug bc it randomly occurs pretty infrequently. But still a huge issue because my app redirects the user to log in again when this happens. Let me know if anyone has any pointers on how I can debug this type of thing
Author
Owner

@bcheung commented on GitHub (Jun 27, 2025):

Might have found a potential lead for my case mentioned above: https://github.com/better-auth/better-auth/issues/2055#issuecomment-3011799925

I stepped through the code and set a breakpoint on line 116 here (inside the sessionDataPayload validity check):
e3ce89562d/packages/better-auth/src/api/routes/session.ts (L106-L122)

And called the get-session endpoint (with disableCookieCache=true) every second on my client app using the better auth client.
After 5ish minutes, I hit the breakpoint...

Correct me if I'm wrong but the logic above validates if the session payload is valid based on the secret and the signature.
I confirmed that for a successful request and a failing request, the secret is the same.
That means the signature or some other data in the payload is incorrect/tampered with relative to the signature. But I can assure you I didn't tamper with it lol.

My initial thought is maybe I'm doing something funky somewhere with hooks or middlewares, but is it even possible to accidentally change the cookie session payload or generate an incorrect signature through these? I wouldn't think so but lmk if I should double check a particular area.

If I have some time, I may try to create a simple repro.
But lmk if anyone else can repro.

UPDATE: After digging into this a bit more, I believe my case is not an issue with better auth. Seemed to be an issue with how I proxied and signed requests in my cloudflare worker. After fixing this, can no longer repro.

UPDATE 2: Actually just ran into the the issue again after I thought I fixed it 😂 I had forgotten to set disableCookieCache=true. When this is set to false, I can't reproduce the issue. Can only reproduce it when set to true with my setup. So the issue still remains, going to see if I can repro with a simpler setup.
When comparing the session data payload of a valid cookie vs an invalid cookie, the only thing that changes is the expiresAt and signature fields. I can see how the expiresAt date changes as we refresh the cookie but don't understand why the signature would be incorrect.

UPDATE 3: Here is the repro: https://github.com/bcheung/better-auth-get-session-bug

@bcheung commented on GitHub (Jun 27, 2025): Might have found a potential lead for my case mentioned above: https://github.com/better-auth/better-auth/issues/2055#issuecomment-3011799925 I stepped through the code and set a breakpoint on line 116 here (inside the sessionDataPayload validity check): https://github.com/better-auth/better-auth/blob/e3ce89562d2704acac80ca41d194cea8a03cc9a7/packages/better-auth/src/api/routes/session.ts#L106-L122 And called the get-session endpoint (with disableCookieCache=true) every second on my client app using the better auth client. After 5ish minutes, I hit the breakpoint... Correct me if I'm wrong but the logic above validates if the session payload is valid based on the secret and the signature. I confirmed that for a successful request and a failing request, the secret is the same. That means the signature or some other data in the payload is incorrect/tampered with relative to the signature. But I can assure you I didn't tamper with it lol. My initial thought is maybe I'm doing something funky somewhere with hooks or middlewares, but is it even possible to accidentally change the cookie session payload or generate an incorrect signature through these? I wouldn't think so but lmk if I should double check a particular area. If I have some time, I may try to create a simple repro. But lmk if anyone else can repro. UPDATE: After digging into this a bit more, I believe my case is not an issue with better auth. Seemed to be an issue with how I proxied and signed requests in my cloudflare worker. After fixing this, can no longer repro. UPDATE 2: Actually just ran into the the issue again after I thought I fixed it 😂 I had forgotten to set disableCookieCache=true. When this is set to false, I can't reproduce the issue. Can only reproduce it when set to true with my setup. So the issue still remains, going to see if I can repro with a simpler setup. When comparing the session data payload of a valid cookie vs an invalid cookie, the only thing that changes is the expiresAt and signature fields. I can see how the expiresAt date changes as we refresh the cookie but don't understand why the signature would be incorrect. UPDATE 3: Here is the repro: https://github.com/bcheung/better-auth-get-session-bug
Author
Owner

@web-deved commented on GitHub (Jun 27, 2025):

In my case, the issue was caused by the hono/language middleware. It seemed to overwrite the cookies after a successful sign-in, so the token couldn't be retained.

import { languageDetector } from 'hono/language'

app.use(
languageDetector({
caches: false // 👈 disable caching
})
)
Disabling the cache like this resolved the issue.

Was already debugging for 2 hours and probably would have been a few more without your comment. Appreciate it, this fixed the issue for me as well. Have you raised the issue with hono?

@web-deved commented on GitHub (Jun 27, 2025): > In my case, the issue was caused by the **hono/language** middleware. It seemed to overwrite the cookies after a successful sign-in, so the token couldn't be retained. > > import { languageDetector } from 'hono/language' > > app.use( > languageDetector({ > caches: false // 👈 disable caching > }) > ) > Disabling the cache like this resolved the issue. Was already debugging for 2 hours and probably would have been a few more without your comment. Appreciate it, this fixed the issue for me as well. Have you raised the issue with hono?
Author
Owner

@bcheung commented on GitHub (Jun 30, 2025):

Might have found a potential lead for my case mentioned above: #2055 (comment)

I stepped through the code and set a breakpoint on line 116 here (inside the sessionDataPayload validity check):
e3ce89562d/packages/better-auth/src/api/routes/session.ts (L106-L122)

And called the get-session endpoint (with disableCookieCache=true) every second on my client app using the better auth client. After 5ish minutes, I hit the breakpoint...

Correct me if I'm wrong but the logic above validates if the session payload is valid based on the secret and the signature. I confirmed that for a successful request and a failing request, the secret is the same. That means the signature or some other data in the payload is incorrect/tampered with relative to the signature. But I can assure you I didn't tamper with it lol.

@Kinfe123 let me know if I should open a new issue for this as I'm not dealing with RSC but I am getting a null session when cookies are present which leads me to believe it could be related.

Here is the repro: https://github.com/bcheung/better-auth-get-session-bug

Sometimes it takes a while for the issue to occur, but just set the breakpoint and let it run until you encounter it. More details in the README

Also btw, in the repro you will notice I don't use the useSession hook because I ran into issues with it, likely related to this: https://github.com/better-auth/better-auth/issues/1006
So instead, I used react query to manage the auth state. I set the refetch interval to 1s for the purpose of this repro.

@bcheung commented on GitHub (Jun 30, 2025): > Might have found a potential lead for my case mentioned above: [#2055 (comment)](https://github.com/better-auth/better-auth/issues/2055#issuecomment-3011799925) > > I stepped through the code and set a breakpoint on line 116 here (inside the sessionDataPayload validity check): https://github.com/better-auth/better-auth/blob/e3ce89562d2704acac80ca41d194cea8a03cc9a7/packages/better-auth/src/api/routes/session.ts#L106-L122 > > And called the get-session endpoint (with disableCookieCache=true) every second on my client app using the better auth client. After 5ish minutes, I hit the breakpoint... > > Correct me if I'm wrong but the logic above validates if the session payload is valid based on the secret and the signature. I confirmed that for a successful request and a failing request, the secret is the same. That means the signature or some other data in the payload is incorrect/tampered with relative to the signature. But I can assure you I didn't tamper with it lol. @Kinfe123 let me know if I should open a new issue for this as I'm not dealing with RSC but I am getting a null session when cookies are present which leads me to believe it could be related. Here is the repro: https://github.com/bcheung/better-auth-get-session-bug Sometimes it takes a while for the issue to occur, but just set the breakpoint and let it run until you encounter it. More details in the README Also btw, in the repro you will notice I don't use the useSession hook because I ran into issues with it, likely related to this: https://github.com/better-auth/better-auth/issues/1006 So instead, I used react query to manage the auth state. I set the refetch interval to 1s for the purpose of this repro.
Author
Owner

@bcheung commented on GitHub (Jul 2, 2025):

@Bekacru @Kinfe123
Don't mean to be annoying, but just want to bump this to see if anyone has ideas on what could be causing this issue.
It seems like a pretty big issue for the session to come back null when the user didn't log out and the session has not expired. It's affecting a handful of my users every day as I see unauthed errors while they use our app. This doesn't even include the untrackable occurences when the user first signs in and gets a null session I currently don't throw an error, it just doesnt trigger a rerender and it keeps them on the sign in page. So the percentage of users affected is not insignificant.

I don't know if I'm just doing something wrong or if it's actually an issue but I made a simple rerpro here:
https://github.com/bcheung/better-auth-get-session-bug

Ideas I have are there may be some issue with updating the expiration and signature, maybe there's a race condition somewhere which is why it happens sometimes but not all the time

I've turned off cookie caching completely and stopped using the disableCookieCache param to avoid this issue for now.

@bcheung commented on GitHub (Jul 2, 2025): @Bekacru @Kinfe123 Don't mean to be annoying, but just want to bump this to see if anyone has ideas on what could be causing this issue. It seems like a pretty big issue for the session to come back null when the user didn't log out and the session has not expired. It's affecting a handful of my users every day as I see unauthed errors while they use our app. This doesn't even include the untrackable occurences when the user first signs in and gets a null session I currently don't throw an error, it just doesnt trigger a rerender and it keeps them on the sign in page. So the percentage of users affected is not insignificant. I don't know if I'm just doing something wrong or if it's actually an issue but I made a simple rerpro here: https://github.com/bcheung/better-auth-get-session-bug Ideas I have are there may be some issue with updating the expiration and signature, maybe there's a race condition somewhere which is why it happens sometimes but not all the time I've turned off cookie caching completely and stopped using the disableCookieCache param to avoid this issue for now.
Author
Owner

@dolanoadriano commented on GitHub (Jul 3, 2025):

it's unbelievable that such a good library contains such a bug...

@dolanoadriano commented on GitHub (Jul 3, 2025): it's unbelievable that such a good library contains such a bug...
Author
Owner

@ian commented on GitHub (Jul 3, 2025):

@dolanoadriano the better-auth library is opensource, feel free to submit a fix.

Otherwise, maybe we should start a bug bounty on this.

@ian commented on GitHub (Jul 3, 2025): @dolanoadriano the better-auth library is opensource, feel free to submit a fix. Otherwise, maybe we should start a bug bounty on this.
Author
Owner

@Ryan0204 commented on GitHub (Jul 20, 2025):

https://github.com/better-auth/better-auth/issues/3470

This solved my problem.

@Ryan0204 commented on GitHub (Jul 20, 2025): https://github.com/better-auth/better-auth/issues/3470 This solved my problem.
Author
Owner

@golddydev commented on GitHub (Jul 21, 2025):

I am also facing this issue. (most of time it works all fine, but sometimes, I faced this issue)
I am using next.js and better auth

next v15.4.2 and better-auth v1.3.1

I do session check on middleware

import { getSessionCookie } from "better-auth/cookies";
...
...
const sessionCookie = getSessionCookie(request);
if (!sessionCookie) {
  const currentUrl = pathname + searchParams;
  const returnUrl = encodeURIComponent(currentUrl);
  return NextResponse.redirect(
    new URL(`/login?returnUrl=${returnUrl}`, request.url),
  );
}

and in layout.tsx, I get session, but it returns null

import "server-only";
import { headers } from "next/headers";

const session = await auth.api.getSession({
  headers: await headers(),
});
@golddydev commented on GitHub (Jul 21, 2025): I am also facing this issue. (most of time it works all fine, but sometimes, I faced this issue) I am using next.js and better auth next v15.4.2 and better-auth v1.3.1 I do session check on middleware ```typescript import { getSessionCookie } from "better-auth/cookies"; ... ... const sessionCookie = getSessionCookie(request); if (!sessionCookie) { const currentUrl = pathname + searchParams; const returnUrl = encodeURIComponent(currentUrl); return NextResponse.redirect( new URL(`/login?returnUrl=${returnUrl}`, request.url), ); } ``` and in layout.tsx, I get session, but it returns null ```typescript import "server-only"; import { headers } from "next/headers"; const session = await auth.api.getSession({ headers: await headers(), }); ```
Author
Owner

@Ariastarcos commented on GitHub (Jul 23, 2025):

Also having this issue. It only happens for me when the auth client is using a Docker network URL (for example, http://api:5000), and never happens in local/development when using localhost URLs.

@Ariastarcos commented on GitHub (Jul 23, 2025): Also having this issue. It only happens for me when the auth client is using a Docker network URL (for example, `http://api:5000`), and never happens in local/development when using localhost URLs.
Author
Owner

@SaviruFr commented on GitHub (Jul 23, 2025):

same here

@SaviruFr commented on GitHub (Jul 23, 2025): same here
Author
Owner

@PacifismPostMortem commented on GitHub (Jul 24, 2025):

@Bekacru I was seeing the same issue when using the cookie cache. The issue is the expires at time is different in the cookie payload and signature when generating the cookie in setCookeCache, so it's an invalid cookie. The reason it's sporadic is it depends on the timing of the code. When I was testing it, sometimes the date would be the same and other times 1 tick off, it was sporadic. I've opened pull request #3283 to fix the bug.

@PacifismPostMortem commented on GitHub (Jul 24, 2025): @Bekacru I was seeing the same issue when using the cookie cache. The issue is the expires at time is different in the cookie payload and signature when generating the cookie in [setCookeCache](https://github.com/better-auth/better-auth/blob/2de1cd27f6177de7e18e57391eb1a0c5dc1cdda3/packages/better-auth/src/cookies/index.ts#L124), so it's an invalid cookie. The reason it's sporadic is it depends on the timing of the code. When I was testing it, sometimes the date would be the same and other times 1 tick off, it was sporadic. I've opened pull request #3283 to fix the bug.
Author
Owner

@ricklabanca commented on GitHub (Jul 24, 2025):

@PacifismPostMortem fantastic catch!!

@ricklabanca commented on GitHub (Jul 24, 2025): @PacifismPostMortem fantastic catch!!
Author
Owner

@ping-maxwell commented on GitHub (Aug 8, 2025):

I will be closing this issue as it's very broad and anything could be the cause of null.
@PacifismPostMortem did a great job at finding that bug and hopefully that's the end of it.
If anyone has any null related get-session issues please open a new issue, and try to be specific in the title to reduce chances of more broad issues that introduce a lot of unrelated noise.

@ping-maxwell commented on GitHub (Aug 8, 2025): I will be closing this issue as it's very broad and anything could be the cause of `null`. @PacifismPostMortem did a great job at finding that bug and hopefully that's the end of it. If anyone has any `null` related get-session issues please open a new issue, and try to be specific in the title to reduce chances of more broad issues that introduce a lot of unrelated noise.
Author
Owner

@pTinosq commented on GitHub (Sep 5, 2025):

For anyone struggling with React Native frontend + some other backend this fix worked:
https://github.com/better-auth/better-auth/issues/3892#issuecomment-3170588827

@pTinosq commented on GitHub (Sep 5, 2025): For anyone struggling with React Native frontend + some other backend this fix worked: https://github.com/better-auth/better-auth/issues/3892#issuecomment-3170588827
Author
Owner

@abdtriedcoding commented on GitHub (Feb 7, 2026):

# Issue: getSession returns null in Next.js Server Components (cookies present)

Hey folks 👋

I’m running into an issue with **Better Auth + Next.js App Router (Server Components)** where the session is always `null` on the server, even though:

- ✅ Auth cookies are correctly set
- ✅ Session works fine on the client side  
- ✅ Cookies are visible in `next/headers`

## Expected behavior

`auth.api.getSession()` should return the active session inside a Server Component, same as it does on the client:

``` ts
const session = await auth.api.getSession({
  headers: await headers(),
});

Actual behavior

The call above always returns null in Server Components, even though:

  • Cookies are present
  • User is authenticated
  • Client-side session works correctly

Temporary workaround (works for me)

I was able to make it work by manually calling the /api/auth/get-session endpoint and forwarding cookies explicitly:

import { cookies } from 'next/headers';
import { auth } from '../../../convex/betterAuth/auth';
import { betterFetch } from '@better-fetch/fetch';

type Session = typeof auth.$Infer.Session;

const getSessionQuery = async ({ cookies }: { cookies: string }) => {
  const { data: session } = await betterFetch<Session>(
    'http://localhost:3000/api/auth/get-session',
    {
      headers: {
        cookie: cookies,
      },
    }
  );

  return session;
};

export default async function DashboardPage() {
  const session = await getSessionQuery({
    cookies: (await cookies()).toString(),
  });

  if (!session) {
    return <div>Not authenticated</div>;
  }

  return <h1>Welcome {JSON.stringify(session)}</h1>;
}

This confirms:

  • Cookies are valid
  • Session endpoint works
  • Issue seems specific to auth.api.getSession() inside Server Components

Question / discussion

  • Is this a known limitation with Next.js Server Components?
  • Am I missing a required config or header forwarding step?
  • Should auth.api.getSession({ headers }) work in Server Components, or is a different approach recommended?

Would love to hear your thoughts!!

@abdtriedcoding commented on GitHub (Feb 7, 2026): ```md # Issue: getSession returns null in Next.js Server Components (cookies present) Hey folks 👋 I’m running into an issue with **Better Auth + Next.js App Router (Server Components)** where the session is always `null` on the server, even though: - ✅ Auth cookies are correctly set - ✅ Session works fine on the client side - ✅ Cookies are visible in `next/headers` ## Expected behavior `auth.api.getSession()` should return the active session inside a Server Component, same as it does on the client: ``` ts const session = await auth.api.getSession({ headers: await headers(), }); ``` ## Actual behavior The call above **always returns `null`** in Server Components, even though: - Cookies are present - User is authenticated - Client-side session works correctly ## Temporary workaround (works for me) I was able to make it work by manually calling the `/api/auth/get-session` endpoint and forwarding cookies explicitly: ```ts import { cookies } from 'next/headers'; import { auth } from '../../../convex/betterAuth/auth'; import { betterFetch } from '@better-fetch/fetch'; type Session = typeof auth.$Infer.Session; const getSessionQuery = async ({ cookies }: { cookies: string }) => { const { data: session } = await betterFetch<Session>( 'http://localhost:3000/api/auth/get-session', { headers: { cookie: cookies, }, } ); return session; }; export default async function DashboardPage() { const session = await getSessionQuery({ cookies: (await cookies()).toString(), }); if (!session) { return <div>Not authenticated</div>; } return <h1>Welcome {JSON.stringify(session)}</h1>; } ``` This confirms: - ✅ Cookies are valid - ✅ Session endpoint works - ❌ Issue seems **specific to `auth.api.getSession()` inside Server Components** ## Question / discussion - Is this a **known limitation** with Next.js Server Components? - Am I missing a **required config** or header forwarding step? - Should `auth.api.getSession({ headers })` work in Server Components, or is a **different approach recommended**? Would love to hear your thoughts!!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#947