[GH-ISSUE #5584] We can’t use getServerSession from Better Auth in Next.js 16 when using use cache. #27613

Closed
opened 2026-04-17 18:42:51 -05:00 by GiteaMirror · 3 comments
Owner

Originally created by @tarifalhasan on GitHub (Oct 26, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/5584

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

Accessing Dynamic data sources inside a cache scope is not supported. If you need this data inside a cached function use headers() outside of the cached function and pass the required dynamic data in as an argument. import { headers } from "next/headers";
import { auth } from "./auth";

export const getServerSession = async () => {
return await auth.api.getSession({ headers: await headers() });
};

Current vs. Expected behavior

Image

What version of Better Auth are you using?

1.3.32

System info

import { headers } from "next/headers";
import { auth } from "./auth";

export const getServerSession = async () => {
  return await auth.api.getSession({ headers: await headers() });
};


import { PrismaClient } from "@/prisma/generated/prisma";
import { betterAuth } from "better-auth";
import { prismaAdapter } from "better-auth/adapters/prisma";
import { nextCookies } from "better-auth/next-js";
import { admin as adminPlugin } from "better-auth/plugins";
import { ac, admin, doctor, user } from "./permissions";

const prisma = new PrismaClient();

export const auth = betterAuth({
  database: prismaAdapter(prisma, { provider: "mongodb" }),
  emailAndPassword: {
    enabled: true,
    async sendResetPassword({ user, url }) {},
  },
  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",
      },
    },
  },
  plugins: [
    adminPlugin({
      adminUserIds: ["BmiEQBumD31Kv4TWFipaoqMnmMGmRFsV"],
      ac: ac,
      adminRoles: ["admin", "user", "doctor"],
      roles: {
        admin,
        user,
        doctor,
      },
    }),
    nextCookies(),
  ],
});

export type Session = typeof auth.$Infer.Session;
export type User = typeof auth.$Infer.Session.user;

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

Client

Auth config (if applicable)

import { betterAuth } from "better-auth"
export const auth = betterAuth({
  emailAndPassword: {  
    enabled: true
  },
});

Additional context

No response

Originally created by @tarifalhasan on GitHub (Oct 26, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/5584 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce Accessing Dynamic data sources inside a cache scope is not supported. If you need this data inside a cached function use `headers()` outside of the cached function and pass the required dynamic data in as an argument. import { headers } from "next/headers"; import { auth } from "./auth"; export const getServerSession = async () => { return await auth.api.getSession({ headers: await headers() }); }; ### Current vs. Expected behavior <img width="991" height="612" alt="Image" src="https://github.com/user-attachments/assets/f0f76b7a-2886-4b2e-8b60-d93899984e9d" /> ### What version of Better Auth are you using? 1.3.32 ### System info ```bash import { headers } from "next/headers"; import { auth } from "./auth"; export const getServerSession = async () => { return await auth.api.getSession({ headers: await headers() }); }; import { PrismaClient } from "@/prisma/generated/prisma"; import { betterAuth } from "better-auth"; import { prismaAdapter } from "better-auth/adapters/prisma"; import { nextCookies } from "better-auth/next-js"; import { admin as adminPlugin } from "better-auth/plugins"; import { ac, admin, doctor, user } from "./permissions"; const prisma = new PrismaClient(); export const auth = betterAuth({ database: prismaAdapter(prisma, { provider: "mongodb" }), emailAndPassword: { enabled: true, async sendResetPassword({ user, url }) {}, }, 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", }, }, }, plugins: [ adminPlugin({ adminUserIds: ["BmiEQBumD31Kv4TWFipaoqMnmMGmRFsV"], ac: ac, adminRoles: ["admin", "user", "doctor"], roles: { admin, user, doctor, }, }), nextCookies(), ], }); export type Session = typeof auth.$Infer.Session; export type User = typeof auth.$Infer.Session.user; ``` ### Which area(s) are affected? (Select all that apply) Client ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth" export const auth = betterAuth({ emailAndPassword: { enabled: true }, }); ``` ### Additional context _No response_
GiteaMirror added the locked label 2026-04-17 18:42:51 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Oct 26, 2025):

Hi @tarifalhasan! I'm Dosu and I’m helping the better-auth team.

This isn't a bug in Better Auth—it's a limitation of Next.js 16's caching model. Next.js 16 doesn't allow accessing dynamic data sources like headers or cookies inside cached functions, which is why calling headers() inside getServerSession causes a runtime error. The recommended fix is to call headers() (or cookies()) outside any cached function and pass the result as an argument to your session retrieval logic example.

For Better Auth, you can restructure your code like this:

import { cookies } from "next/headers";
import { auth } from "./auth";

// Call cookies() outside the cached function and pass it in
export async function getServerSession(cookieHeader: string) {
  return await auth.api.getSession({ headers: { Cookie: cookieHeader } });
}

// Usage example (outside cache scope)
const cookieHeader = cookies().toString();
const session = await getServerSession(cookieHeader);

If your auth server is remote, proxy the session request through an API route or server action, forwarding the cookie header explicitly workaround.

Also, make sure your cookie settings use sameSite: "none" and secure: true for cross-origin requests details.

This pattern aligns with both Next.js and Better Auth's expectations and avoids the runtime error.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X

<!-- gh-comment-id:3448035912 --> @dosubot[bot] commented on GitHub (Oct 26, 2025): <!-- Greeting --> Hi @tarifalhasan! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> This isn't a bug in Better Auth—it's a limitation of Next.js 16's caching model. Next.js 16 doesn't allow accessing dynamic data sources like headers or cookies inside cached functions, which is why calling `headers()` inside `getServerSession` causes a runtime error. The recommended fix is to call `headers()` (or `cookies()`) outside any cached function and pass the result as an argument to your session retrieval logic [example](https://github.com/better-auth/better-auth/issues/4188#issuecomment-3217783603). For Better Auth, you can restructure your code like this: ```ts import { cookies } from "next/headers"; import { auth } from "./auth"; // Call cookies() outside the cached function and pass it in export async function getServerSession(cookieHeader: string) { return await auth.api.getSession({ headers: { Cookie: cookieHeader } }); } // Usage example (outside cache scope) const cookieHeader = cookies().toString(); const session = await getServerSession(cookieHeader); ``` If your auth server is remote, proxy the session request through an API route or server action, forwarding the cookie header explicitly [workaround](https://github.com/better-auth/better-auth/issues/4044#issuecomment-3193722222). Also, make sure your cookie settings use `sameSite: "none"` and `secure: true` for cross-origin requests [details](https://github.com/better-auth/better-auth/issues/4188). This pattern aligns with both Next.js and Better Auth's expectations and avoids the runtime error. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/78f97395-a4a1-48a8-b0ed-5ef08b6ba388?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/78f97395-a4a1-48a8-b0ed-5ef08b6ba388?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/78f97395-a4a1-48a8-b0ed-5ef08b6ba388?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/78f97395-a4a1-48a8-b0ed-5ef08b6ba388?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/78f97395-a4a1-48a8-b0ed-5ef08b6ba388?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/78f97395-a4a1-48a8-b0ed-5ef08b6ba388?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/78f97395-a4a1-48a8-b0ed-5ef08b6ba388?feedback_type=other)</sup>&nbsp;&nbsp;[![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/issues/5584)
Author
Owner

@tarifalhasan commented on GitHub (Oct 26, 2025):

Thanks, it's working! Just make sure to use await when getting the cookies, like this:

const cookieHeader = (await cookies()).toString();
const session = await getServerSession(cookieHeader);
<!-- gh-comment-id:3448124885 --> @tarifalhasan commented on GitHub (Oct 26, 2025): Thanks, it's working! Just make sure to use await when getting the cookies, like this: ``` const cookieHeader = (await cookies()).toString(); const session = await getServerSession(cookieHeader); ```
Author
Owner

@dosubot[bot] commented on GitHub (Jan 26, 2026):

Hi, @tarifalhasan. I'm Dosu, and I'm helping the better-auth team manage their backlog and am marking this issue as stale.

Issue Summary:

  • You reported issues using getServerSession inside a cached function in Next.js 16 with Better Auth v1.3.32 due to dynamic data access restrictions.
  • The root cause is a Next.js limitation preventing dynamic data access inside cached functions.
  • The recommended workaround is to call headers() or cookies() outside the cached function and pass the data as arguments.
  • You confirmed that this workaround works when cookies() is properly awaited.
  • The discussion included code examples and best practices for session retrieval in this context.

Next Steps:

  • Please let me know if this issue is still relevant with the latest version of better-auth by commenting here.
  • If I don’t hear back within 7 days, I will automatically close this issue.

Thanks for your understanding and contribution!

<!-- gh-comment-id:3800420918 --> @dosubot[bot] commented on GitHub (Jan 26, 2026): Hi, @tarifalhasan. I'm [Dosu](https://dosu.dev), and I'm helping the better-auth team manage their backlog and am marking this issue as stale. **Issue Summary:** - You reported issues using getServerSession inside a cached function in Next.js 16 with Better Auth v1.3.32 due to dynamic data access restrictions. - The root cause is a Next.js limitation preventing dynamic data access inside cached functions. - The recommended workaround is to call headers() or cookies() outside the cached function and pass the data as arguments. - You confirmed that this workaround works when cookies() is properly awaited. - The discussion included code examples and best practices for session retrieval in this context. **Next Steps:** - Please let me know if this issue is still relevant with the latest version of better-auth by commenting here. - If I don’t hear back within 7 days, I will automatically close this issue. Thanks for your understanding and contribution!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#27613