[GH-ISSUE #7105] Honojs + Nextjs giving null erro while using authClient.api.getSession #10729

Closed
opened 2026-04-13 07:02:38 -05:00 by GiteaMirror · 18 comments
Owner

Originally created by @kuldeepsaini23 on GitHub (Jan 3, 2026).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/7105

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

To reproduce it, you simply have to create a Honojs + nextjs project and have to deploy it

Current vs. Expected behavior

import { emailOTPClient } from "better-auth/client/plugins";
import { createAuthClient } from "better-auth/react";

export const authClient = createAuthClient({
baseURL: process.env.NEXT_PUBLIC_AUTH_BACKEND_URL, // Dynamic base URL based on environment
plugins: [emailOTPClient()],
});

I first tried retrieving the session using authClient.api.getSession, but it always returned null. After researching, I found that I should use a server-side approach and implemented the method below.

However, even with this approach, I am still getting null as the session.

"use server";
import { cookies } from "next/headers";
import type { UserSession } from "@/types/auth";

export const getServerSession = async (): Promise<UserSession | null> => {
try {
const cookieHeader = (await cookies()).toString();
console.log("Cookie header:", cookieHeader);

const res = await fetch(
  `${process.env.NEXT_PUBLIC_AUTH_BACKEND_URL}/api/auth/get-session`,
  {
    headers: { Cookie: cookieHeader },
    credentials: "include",
  }
);

if (!res.ok) return null;

const data = await res.json();
console.log("Session retrieved successfully:", data);

return data as UserSession;

} catch (err) {
const error = err as Error;
console.error("Exception in getServerSession:", {
message: error.message,
stack: error.stack,
cause: error.cause,
});
return null;
}
};

What version of Better Auth are you using?

^1.4.10

System info

Nextjs (Frontend)

{
  "system": {
    "platform": "win32",
    "arch": "x64",
    "version": "Windows 11 Pro",
    "release": "10.0.26200",
    "cpuCount": 12,
    "cpuModel": "AMD Ryzen 5 7600 6-Core Processor              ",
    "totalMemory": "15.19 GB",
    "freeMemory": "1.76 GB"
  },
  "node": {
    "version": "v22.17.0",
    "env": "development"
  },
  "packageManager": {
    "name": "npm",
    "version": "11.7.0"
  },
  "frameworks": [
    {
      "name": "next",
      "version": "^16.1.1"
    },
    {
      "name": "react",
      "version": "^19.2.3"
    }
  ],
  "databases": null,
  "betterAuth": {
    "version": "^1.4.9",
    "config": null
  }
}

Honojs(Backend)
{
  "system": {
    "platform": "win32",
    "arch": "x64",
    "version": "Windows 11 Pro",
    "release": "10.0.26200",
    "cpuCount": 12,
    "cpuModel": "AMD Ryzen 5 7600 6-Core Processor              ",
    "totalMemory": "15.19 GB",
    "freeMemory": "1.76 GB"
  },
  "node": {
    "version": "v22.17.0",
    "env": "development"
  },
  "packageManager": {
    "name": "npm",
    "version": "10.9.2"
  },
  "frameworks": null,
  "databases": [
    {
      "name": "@prisma/client",
      "version": "6.18.0"
    }
  ],
  "betterAuth": {
    "version": "Unknown",
    "config": null
  }
}

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

Client

Auth config (if applicable)

/* eslint-disable @typescript-eslint/no-explicit-any */
import { SendOTP } from '@backend/aws';
import { prisma } from '@backend/db';
import { loadEnv } from '@backend/runtime';
import type { BetterAuthOptions } from 'better-auth';
import { betterAuth } from 'better-auth';
import { prismaAdapter } from 'better-auth/adapters/prisma';
import { APIError, createAuthMiddleware } from 'better-auth/api';
import {
  openAPI,
  organization,
  jwt,
  admin,
  customSession,
  emailOTP,
  username,
} from 'better-auth/plugins';

import { UserProfileInputSchema } from './schema';

loadEnv();

/**
 * Alias for the Better Auth configuration interface inferred from `betterAuth`.
 */
// type AuthInterface = ReturnType<typeof betterAuth>;

/**
 * Better Auth server configuration for the auth microservice.
 *
 * Environment variables used:
 * - BETTER_AUTH_URL: Public base URL of the auth service (e.g., https://auth.example.com)
 * - GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET: Google OAuth credentials
 * - GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET: GitHub OAuth credentials
 * - BETTER_AUTH_TRUSTED_ORIGIN: Allowed origin for cross-origin requests to auth endpoints
 */
const options = {
  /**
   * Public base URL that Better Auth uses to generate callback URLs.
   */
  baseURL: process.env.BETTER_AUTH_URL,
  /**
   * Database adapter configuration. Uses Prisma connected to a MongoDB provider.
   */
  database: prismaAdapter(prisma, {
    provider: 'mongodb',
  }),
  /**
   * OAuth social provider configuration.
   */
  socialProviders: {
    /** Google OAuth provider settings. */
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID as string,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
      display: 'popup',
    },
    /** GitHub OAuth provider settings. */
    github: {
      clientId: process.env.GITHUB_CLIENT_ID as string,
      clientSecret: process.env.GITHUB_CLIENT_SECRET,
    },
  },
  /**
   * Disable username/password flow; using federated login and OTP instead.
   */
  emailAndPassword: {
    enabled: false,
    // requireEmailVerification:true,
  },
  plugins: [
    openAPI({
      theme: 'bluePlanet',
    }),
    username({
      minUsernameLength: 4,
      maxUsernameLength: 12,
    }),
    emailOTP({
      /**
       * Send a verification OTP to the user for the specified action type.
       *
       * @param params.email - Recipient email address
       * @param params.otp - One-time password to be delivered
       * @param params.type - OTP flow type (e.g., "sign-in", "email-verification")
       */
      sendVerificationOTP: async ({ email, otp, type }) => {
        if (type === 'sign-in') {
          console.log(`sending otp to ${email} : ${otp}`);
          // try {
          //   const response = await SendOTP(email,otp);

          //   if(!response.success){
          //     throw new APIError('BAD_REQUEST',{ message: response.message , code: response.code });
          //   }

          // } catch (error:any) {
          //   throw new APIError('BAD_REQUEST', {
          //     message: error.message || "Failed to send email.",
          //     code: error.body.code || error.code || "EMAIL_SERVICE_ERROR"
          //   })
          // }
        }
        // if(type === 'email-verification'){
        //   console.log(`sending verification otp to ${email} : ${otp}`);
        // }
      },
      // sendVerificationOnSignUp:true,
      // overrideDefaultEmailVerification:true
    }),
    admin({
      /**
       * Role-based admin configuration.
       * Users default to the "user" role; "admin" and "superAdmin" are elevated.
       */
      adminUserIds: ['BH4XFH0reiAv05INPlm62DKJkRRpuZG9'],
      adminRoles: ['admin', 'superAdmin'],
      defaultRole: 'user',
    }),
    jwt({
      jwt: {
        /**
         * Define additional fields to embed into the JWT payload for the user.
         *
         * @param params.user - The authenticated user record
         * @returns Minimal payload used downstream for authorization decisions
         */
        definePayload: ({ user }) => {
          return {
            id: user.id,
            name: user.name,
            role: user.role,
          };
        },
      },
    }),
    organization({
      /** Enable team/organization features for multi-tenant scenarios. */
      teams: { enabled: true },
    }),
  ],
  /**
   * Database hooks for reacting to lifecycle events.
   * Here we create a companion `userProfile` when a new user is created.
   */
  databaseHooks: {
    user: {
      create: {
        async before(user) {
          const username =
            user.email.split('@')[0] +
            Date.now().toString() +
            Math.floor(Math.random() * 1000).toString();

          const name = user.name === '' ? user.email.split('@')[0] : user.name;
          const image = user.image
            ? user.image
            : `https://api.dicebear.com/7.x/initials/svg?seed=${name}`;

          return {
            data: {
              ...user,
              name,
              username,
              image,
            },
          };
        },

        /**
         * Runs after a user record is created.
         *
         * @param user - The newly created user entity
         * @param context - Hook context from Better Auth
         */
        async after(user) {
          // *Format 2025-11-14 (IST) not
          const today = new Date(new Date().setHours(24, 0, 0, 0)).toISOString().split('T')[0];

          await prisma.user.update({
            where: {
              id: user.id,
            },
            data: {
              userProfile: {
                create: {},
              },
              editorSettings: {
                create: {},
              },
              userOverallProgress: {
                create: {},
              },
              userGamificationProfile: {
                create: {
                  coinBalance: 100, // TODO: give coins to user when first sign-up
                },
              },
              userStreak: {
                create: {
                  streak: 1,
                  longestStreak: 1,
                  streakDates: { set: [today] },
                },
              },
            },
          });
        },
      },
      update: {
        async before(user) {
          const image = user.image
            ? user.image
            : `https://api.dicebear.com/7.x/initials/svg?seed=${user.name}`;
          return {
            data: {
              ...user,
              image,
            },
          };
        },
      },
    },
  },
  hooks: {
    after: createAuthMiddleware(async (ctx) => {
      if (ctx.path === '/update-user') {
        if (ctx?.body) {
          try {
            const userId = ctx.context.newSession?.user.id;
            const data = UserProfileInputSchema.parse(ctx.body);
            await prisma.userProfile.update({
              where: {
                userId,
              },
              data: data,
            });
          } catch (error: any) {
            if (error.name === 'ZodError') {
              const zodError = JSON.parse(error);
              console.log(zodError);
              throw new APIError('BAD_REQUEST', {
                message: `${zodError[0].path[0]} : ${zodError[0].message}`,
                code: zodError[0].code,
              });
            } else {
              throw new APIError('INTERNAL_SERVER_ERROR', {
                message: 'something went wrong.',
                code: 'internal_server_error',
                cause: error,
              });
            }
          }
        }
      }
    }),
  },
  session: {
    cookieCache: {
      /**
       * Cache sessions in a signed cookie for faster reads.
       */
      enabled: false, // Disable cookie cache to prevent UI mismatch issues
      maxAge: 10 * 60, // Cache duration in seconds
    },
  },
  user: {
    additionalFields: {
      role: { type: 'string' },
    },
    changeEmail: {
      enabled: false,
      // async sendChangeEmailVerification({ user, newEmail ,url, token }, request){
      //   console.log(`change email url for ${newEmail} : ${url}`);
      // }
    },
  },
  /**
   * Allowed cross-origin request origin(s) for Better Auth endpoints.
   */
  trustedOrigins: [process.env.BETTER_AUTH_TRUSTED_ORIGIN as string, 'http://localhost:3000'],
  secret: process.env.BETTER_AUTH_SECRET,
  advanced: {
    defaultCookieAttributes: {
      sameSite: 'none',
      secure: true,
      partitioned: true,
    },
    cookies: {
      state: {
        attributes: {
          sameSite: 'none',
          secure: true,
        },
      },
    },
  },
} satisfies BetterAuthOptions;

const auth = betterAuth({
  ...options,
  plugins: [
    ...(options.plugins ?? []),
    /**
     * Augment the session payload with additional user data hydrated from the database.
     * Fetches the user's profile and returns it alongside the standard user object.
     *
     * @param params.session - The computed session object
     * @param params.user - The authenticated user
     * @returns The updated session and user object including `profile`
     */
    customSession(async ({ user, session }) => {
      // now both user and session will infer the fields added by plugins and your custom fields
      const profile = await prisma.user.findUnique({
        where: {
          id: user.id, // user.role should now be available
        },
        include: {
          userProfile: true,
          userStreak: true,
          userGamificationProfile: true,
          subscription: true,
          bookmarks: true,
        },
      });

      let isActiveSubscription = false;
      const subscription = profile?.subscription;

      if (!subscription) {
        isActiveSubscription = false;
      } else {
        const current_time = Date.now() / 1000;
        if (subscription.accessUntil === null) {
          isActiveSubscription = false;
        } else {
          isActiveSubscription = subscription.accessUntil > current_time ? true : false;
        }
        // switch (subscription.status) {
        //   case 'ACTIVE':
        //     isActiveSubscription = true;
        //     break;
        //   case 'CANCELLED':
        //   case 'COMPLETED':
        //     if (subscription.accessUntil === null) {
        //       isActiveSubscription = false;
        //     } else {
        //       isActiveSubscription = subscription.accessUntil > current_time ? true : false;
        //     }
        //     break;
        //   case 'CREATED':
        //   case 'HALTED':
        //   case 'PAUSED':
        //   case 'PENDING':
        //     isActiveSubscription = false;
        //     break;
        //   default:
        //     isActiveSubscription = false;
        //     break;
        // }
      }

      return {
        user: {
          ...user,
          ...profile,
          isActiveSubscription,
        },
        session,
      };
    }, options), // pass options here
  ],
});

export { auth };

Additional context

Everything is working fine in local environment but not in production environment.

Originally created by @kuldeepsaini23 on GitHub (Jan 3, 2026). Original GitHub issue: https://github.com/better-auth/better-auth/issues/7105 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce To reproduce it, you simply have to create a Honojs + nextjs project and have to deploy it ### Current vs. Expected behavior import { emailOTPClient } from "better-auth/client/plugins"; import { createAuthClient } from "better-auth/react"; export const authClient = createAuthClient({ baseURL: process.env.NEXT_PUBLIC_AUTH_BACKEND_URL, // Dynamic base URL based on environment plugins: [emailOTPClient()], }); I first tried retrieving the session using authClient.api.getSession, but it always returned null. After researching, I found that I should use a server-side approach and implemented the method below. However, even with this approach, I am still getting null as the session. "use server"; import { cookies } from "next/headers"; import type { UserSession } from "@/types/auth"; export const getServerSession = async (): Promise<UserSession | null> => { try { const cookieHeader = (await cookies()).toString(); console.log("Cookie header:", cookieHeader); const res = await fetch( `${process.env.NEXT_PUBLIC_AUTH_BACKEND_URL}/api/auth/get-session`, { headers: { Cookie: cookieHeader }, credentials: "include", } ); if (!res.ok) return null; const data = await res.json(); console.log("Session retrieved successfully:", data); return data as UserSession; } catch (err) { const error = err as Error; console.error("Exception in getServerSession:", { message: error.message, stack: error.stack, cause: error.cause, }); return null; } }; ### What version of Better Auth are you using? ^1.4.10 ### System info ```bash Nextjs (Frontend) { "system": { "platform": "win32", "arch": "x64", "version": "Windows 11 Pro", "release": "10.0.26200", "cpuCount": 12, "cpuModel": "AMD Ryzen 5 7600 6-Core Processor ", "totalMemory": "15.19 GB", "freeMemory": "1.76 GB" }, "node": { "version": "v22.17.0", "env": "development" }, "packageManager": { "name": "npm", "version": "11.7.0" }, "frameworks": [ { "name": "next", "version": "^16.1.1" }, { "name": "react", "version": "^19.2.3" } ], "databases": null, "betterAuth": { "version": "^1.4.9", "config": null } } Honojs(Backend) { "system": { "platform": "win32", "arch": "x64", "version": "Windows 11 Pro", "release": "10.0.26200", "cpuCount": 12, "cpuModel": "AMD Ryzen 5 7600 6-Core Processor ", "totalMemory": "15.19 GB", "freeMemory": "1.76 GB" }, "node": { "version": "v22.17.0", "env": "development" }, "packageManager": { "name": "npm", "version": "10.9.2" }, "frameworks": null, "databases": [ { "name": "@prisma/client", "version": "6.18.0" } ], "betterAuth": { "version": "Unknown", "config": null } } ``` ### Which area(s) are affected? (Select all that apply) Client ### Auth config (if applicable) ```typescript /* eslint-disable @typescript-eslint/no-explicit-any */ import { SendOTP } from '@backend/aws'; import { prisma } from '@backend/db'; import { loadEnv } from '@backend/runtime'; import type { BetterAuthOptions } from 'better-auth'; import { betterAuth } from 'better-auth'; import { prismaAdapter } from 'better-auth/adapters/prisma'; import { APIError, createAuthMiddleware } from 'better-auth/api'; import { openAPI, organization, jwt, admin, customSession, emailOTP, username, } from 'better-auth/plugins'; import { UserProfileInputSchema } from './schema'; loadEnv(); /** * Alias for the Better Auth configuration interface inferred from `betterAuth`. */ // type AuthInterface = ReturnType<typeof betterAuth>; /** * Better Auth server configuration for the auth microservice. * * Environment variables used: * - BETTER_AUTH_URL: Public base URL of the auth service (e.g., https://auth.example.com) * - GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET: Google OAuth credentials * - GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET: GitHub OAuth credentials * - BETTER_AUTH_TRUSTED_ORIGIN: Allowed origin for cross-origin requests to auth endpoints */ const options = { /** * Public base URL that Better Auth uses to generate callback URLs. */ baseURL: process.env.BETTER_AUTH_URL, /** * Database adapter configuration. Uses Prisma connected to a MongoDB provider. */ database: prismaAdapter(prisma, { provider: 'mongodb', }), /** * OAuth social provider configuration. */ socialProviders: { /** Google OAuth provider settings. */ google: { clientId: process.env.GOOGLE_CLIENT_ID as string, clientSecret: process.env.GOOGLE_CLIENT_SECRET, display: 'popup', }, /** GitHub OAuth provider settings. */ github: { clientId: process.env.GITHUB_CLIENT_ID as string, clientSecret: process.env.GITHUB_CLIENT_SECRET, }, }, /** * Disable username/password flow; using federated login and OTP instead. */ emailAndPassword: { enabled: false, // requireEmailVerification:true, }, plugins: [ openAPI({ theme: 'bluePlanet', }), username({ minUsernameLength: 4, maxUsernameLength: 12, }), emailOTP({ /** * Send a verification OTP to the user for the specified action type. * * @param params.email - Recipient email address * @param params.otp - One-time password to be delivered * @param params.type - OTP flow type (e.g., "sign-in", "email-verification") */ sendVerificationOTP: async ({ email, otp, type }) => { if (type === 'sign-in') { console.log(`sending otp to ${email} : ${otp}`); // try { // const response = await SendOTP(email,otp); // if(!response.success){ // throw new APIError('BAD_REQUEST',{ message: response.message , code: response.code }); // } // } catch (error:any) { // throw new APIError('BAD_REQUEST', { // message: error.message || "Failed to send email.", // code: error.body.code || error.code || "EMAIL_SERVICE_ERROR" // }) // } } // if(type === 'email-verification'){ // console.log(`sending verification otp to ${email} : ${otp}`); // } }, // sendVerificationOnSignUp:true, // overrideDefaultEmailVerification:true }), admin({ /** * Role-based admin configuration. * Users default to the "user" role; "admin" and "superAdmin" are elevated. */ adminUserIds: ['BH4XFH0reiAv05INPlm62DKJkRRpuZG9'], adminRoles: ['admin', 'superAdmin'], defaultRole: 'user', }), jwt({ jwt: { /** * Define additional fields to embed into the JWT payload for the user. * * @param params.user - The authenticated user record * @returns Minimal payload used downstream for authorization decisions */ definePayload: ({ user }) => { return { id: user.id, name: user.name, role: user.role, }; }, }, }), organization({ /** Enable team/organization features for multi-tenant scenarios. */ teams: { enabled: true }, }), ], /** * Database hooks for reacting to lifecycle events. * Here we create a companion `userProfile` when a new user is created. */ databaseHooks: { user: { create: { async before(user) { const username = user.email.split('@')[0] + Date.now().toString() + Math.floor(Math.random() * 1000).toString(); const name = user.name === '' ? user.email.split('@')[0] : user.name; const image = user.image ? user.image : `https://api.dicebear.com/7.x/initials/svg?seed=${name}`; return { data: { ...user, name, username, image, }, }; }, /** * Runs after a user record is created. * * @param user - The newly created user entity * @param context - Hook context from Better Auth */ async after(user) { // *Format 2025-11-14 (IST) not const today = new Date(new Date().setHours(24, 0, 0, 0)).toISOString().split('T')[0]; await prisma.user.update({ where: { id: user.id, }, data: { userProfile: { create: {}, }, editorSettings: { create: {}, }, userOverallProgress: { create: {}, }, userGamificationProfile: { create: { coinBalance: 100, // TODO: give coins to user when first sign-up }, }, userStreak: { create: { streak: 1, longestStreak: 1, streakDates: { set: [today] }, }, }, }, }); }, }, update: { async before(user) { const image = user.image ? user.image : `https://api.dicebear.com/7.x/initials/svg?seed=${user.name}`; return { data: { ...user, image, }, }; }, }, }, }, hooks: { after: createAuthMiddleware(async (ctx) => { if (ctx.path === '/update-user') { if (ctx?.body) { try { const userId = ctx.context.newSession?.user.id; const data = UserProfileInputSchema.parse(ctx.body); await prisma.userProfile.update({ where: { userId, }, data: data, }); } catch (error: any) { if (error.name === 'ZodError') { const zodError = JSON.parse(error); console.log(zodError); throw new APIError('BAD_REQUEST', { message: `${zodError[0].path[0]} : ${zodError[0].message}`, code: zodError[0].code, }); } else { throw new APIError('INTERNAL_SERVER_ERROR', { message: 'something went wrong.', code: 'internal_server_error', cause: error, }); } } } } }), }, session: { cookieCache: { /** * Cache sessions in a signed cookie for faster reads. */ enabled: false, // Disable cookie cache to prevent UI mismatch issues maxAge: 10 * 60, // Cache duration in seconds }, }, user: { additionalFields: { role: { type: 'string' }, }, changeEmail: { enabled: false, // async sendChangeEmailVerification({ user, newEmail ,url, token }, request){ // console.log(`change email url for ${newEmail} : ${url}`); // } }, }, /** * Allowed cross-origin request origin(s) for Better Auth endpoints. */ trustedOrigins: [process.env.BETTER_AUTH_TRUSTED_ORIGIN as string, 'http://localhost:3000'], secret: process.env.BETTER_AUTH_SECRET, advanced: { defaultCookieAttributes: { sameSite: 'none', secure: true, partitioned: true, }, cookies: { state: { attributes: { sameSite: 'none', secure: true, }, }, }, }, } satisfies BetterAuthOptions; const auth = betterAuth({ ...options, plugins: [ ...(options.plugins ?? []), /** * Augment the session payload with additional user data hydrated from the database. * Fetches the user's profile and returns it alongside the standard user object. * * @param params.session - The computed session object * @param params.user - The authenticated user * @returns The updated session and user object including `profile` */ customSession(async ({ user, session }) => { // now both user and session will infer the fields added by plugins and your custom fields const profile = await prisma.user.findUnique({ where: { id: user.id, // user.role should now be available }, include: { userProfile: true, userStreak: true, userGamificationProfile: true, subscription: true, bookmarks: true, }, }); let isActiveSubscription = false; const subscription = profile?.subscription; if (!subscription) { isActiveSubscription = false; } else { const current_time = Date.now() / 1000; if (subscription.accessUntil === null) { isActiveSubscription = false; } else { isActiveSubscription = subscription.accessUntil > current_time ? true : false; } // switch (subscription.status) { // case 'ACTIVE': // isActiveSubscription = true; // break; // case 'CANCELLED': // case 'COMPLETED': // if (subscription.accessUntil === null) { // isActiveSubscription = false; // } else { // isActiveSubscription = subscription.accessUntil > current_time ? true : false; // } // break; // case 'CREATED': // case 'HALTED': // case 'PAUSED': // case 'PENDING': // isActiveSubscription = false; // break; // default: // isActiveSubscription = false; // break; // } } return { user: { ...user, ...profile, isActiveSubscription, }, session, }; }, options), // pass options here ], }); export { auth }; ``` ### Additional context Everything is working fine in local environment but not in production environment.
GiteaMirror added the locked label 2026-04-13 07:02:38 -05:00
Author
Owner

@better-auth-agent[bot] commented on GitHub (Jan 3, 2026):

It sounds like you're experiencing a persistent issue with the authClient.api.getSession method returning null when used with Hono.js and Next.js, particularly in a production environment. Here are some steps you can take to troubleshoot this:

  1. Check Environment Variables: Make sure that the environment variables such as NEXT_PUBLIC_AUTH_BACKEND_URL, which defines your backend's URL, are correctly set in your production environment. These might differ from your local setup.

  2. Cookies Configuration: Verify that your cookies are being sent correctly. Since you are using authClient.api.getSession, ensure that cookies are included in your fetch requests. Ensure the credentials: "include" option is set properly in your fetch configuration.

  3. Server-Side Session Retrieval: Instead of using authClient.api.getSession on the client-side, if there are discrepancies between your client and server environment settings, try using the server-side method (e.g., via fetch directly to your backend's session endpoint).

  4. Inspect Cookie Headers: Add logging in your server-side code before the session retrieval to see what cookie headers are being sent. You might find discrepancies or missing cookies.

  5. Update to Latest Version: Ensure that you are using the latest version of Better Auth, as bugs are often addressed in newer releases.

  6. Known Issues: Check if there are any known issues reported on GitHub related to sessions returning null; users have experienced similar problems in various discussions, and sometimes rolling back to an earlier version might help. For example, issues with versions can often cause unexpected behavior with session management in Next.js.

If you've gone through all these steps and the issue persists, feel free to tag @bekacru or @ping__ for further assistance from the Better Auth team!

What specific errors or behaviors are you observing in the production environment compared to your local setup?

If you need more help, tag @better-auth-agent in a comment so I can respond.

DiagramDiscordGitHub

Diagram Join Star

<!-- gh-comment-id:3706916434 --> @better-auth-agent[bot] commented on GitHub (Jan 3, 2026): It sounds like you're experiencing a persistent issue with the `authClient.api.getSession` method returning null when used with Hono.js and Next.js, particularly in a production environment. Here are some steps you can take to troubleshoot this: 1. **Check Environment Variables**: Make sure that the environment variables such as `NEXT_PUBLIC_AUTH_BACKEND_URL`, which defines your backend's URL, are correctly set in your production environment. These might differ from your local setup. 2. **Cookies Configuration**: Verify that your cookies are being sent correctly. Since you are using `authClient.api.getSession`, ensure that cookies are included in your fetch requests. Ensure the `credentials: "include"` option is set properly in your fetch configuration. 3. **Server-Side Session Retrieval**: Instead of using `authClient.api.getSession` on the client-side, if there are discrepancies between your client and server environment settings, try using the server-side method (e.g., via `fetch` directly to your backend's session endpoint). 4. **Inspect Cookie Headers**: Add logging in your server-side code before the session retrieval to see what cookie headers are being sent. You might find discrepancies or missing cookies. 5. **Update to Latest Version**: Ensure that you are using the latest version of Better Auth, as bugs are often addressed in newer releases. 6. **Known Issues**: Check if there are any known issues reported on GitHub related to sessions returning null; users have experienced similar problems in various discussions, and sometimes rolling back to an earlier version might help. For example, issues with versions can often cause unexpected behavior with session management in Next.js. If you've gone through all these steps and the issue persists, feel free to tag @bekacru or @ping__ for further assistance from the Better Auth team! What specific errors or behaviors are you observing in the production environment compared to your local setup? _If you need more help, tag @better-auth-agent in a comment so I can respond._ <!-- bot:webhook reply v1 --> [Diagram](https://repodiagrams.s3.eu-north-1.amazonaws.com/skyvern_ultra_detailed_interactive.html) • [Discord](https://discord.gg/fG2XXEuQX3) • [GitHub](https://github.com/Skyvern-AI/Skyvern) [![Diagram](https://img.shields.io/badge/Diagram-2b3137?style=flat-square)](https://repodiagrams.s3.eu-north-1.amazonaws.com/skyvern_ultra_detailed_interactive.html) [![Join](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&style=flat-square)](https://discord.gg/fG2XXEuQX3) [![Star](https://img.shields.io/badge/star-181717?logo=github&logoColor=white&style=flat-square)](https://github.com/Skyvern-AI/Skyvern)
Author
Owner

@kuldeepsaini23 commented on GitHub (Jan 3, 2026):

@Bekacru

<!-- gh-comment-id:3706917064 --> @kuldeepsaini23 commented on GitHub (Jan 3, 2026): @Bekacru
Author
Owner

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

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

Your issue is almost certainly caused by cookie/session handling differences between local and production, especially with cross-origin setups and recent Better Auth versions.

Here’s what you need to do:

  1. Enable session cookie cache: In Better Auth v1.4.x+, you must set session.cookieCache.enabled: true in your backend config. Without this, the session_data cookie isn’t set/read and getSession will always return null in production [source].

  2. Set the cookie cache strategy: If enabling cookieCache alone doesn’t fix it, set session.cookieCache.strategy: 'jwt' (or 'base64-hmac' if you’re migrating from older versions). This resolves environment-specific issues for many users [source].

  3. Check your cookies in production: Use browser dev tools to confirm that after sign-in, you see cookies like __Secure-better-auth.session_token and __Secure-better-auth.session_data (or chunked variants) set for your frontend domain. If they’re missing, check for HTTPS, correct domain, and that no proxy/middleware is stripping Set-Cookie headers [source].

  4. Cookie settings: For cross-origin, cookies must have sameSite: 'none' and secure: true. Both frontend and backend must be served over HTTPS, and your baseURL and trustedOrigins must match your deployed domains [source].

  5. Explicitly forward cookies: In Next.js server components, always forward the cookie header from the browser to your auth backend (as you’re doing). If frontend and backend are on different domains, consider proxying session requests through a Next.js API route to keep cookies on the same domain [source].

  6. Next.js 16 caveat: Make sure you call cookies() or headers() outside of any cached function and pass the cookie header explicitly to your session retrieval logic. Calling them inside cached functions can cause getSession to return null [source].

  7. Debugging: Enable debug logging on both frontend and backend. Check actual cookie values and backend logs for validation errors or missing cookies.

If you follow these steps and still get null, double-check for any proxy/CDN/middleware that might strip cookies, and ensure your environment variables (like NEXT_PUBLIC_AUTH_BACKEND_URL and BETTER_AUTH_URL) are set correctly for production.

Let me know if you want a minimal config example or have specific debug output!

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

<!-- gh-comment-id:3706920680 --> @dosubot[bot] commented on GitHub (Jan 3, 2026): <!-- Greeting --> Hi @kuldeepsaini23! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> Your issue is almost certainly caused by cookie/session handling differences between local and production, especially with cross-origin setups and recent Better Auth versions. Here’s what you need to do: 1. **Enable session cookie cache:** In Better Auth v1.4.x+, you must set `session.cookieCache.enabled: true` in your backend config. Without this, the session_data cookie isn’t set/read and getSession will always return null in production [[source]](https://github.com/better-auth/better-auth/issues/6672). 2. **Set the cookie cache strategy:** If enabling cookieCache alone doesn’t fix it, set `session.cookieCache.strategy: 'jwt'` (or `'base64-hmac'` if you’re migrating from older versions). This resolves environment-specific issues for many users [[source]](https://github.com/better-auth/better-auth/issues/7008). 3. **Check your cookies in production:** Use browser dev tools to confirm that after sign-in, you see cookies like `__Secure-better-auth.session_token` and `__Secure-better-auth.session_data` (or chunked variants) set for your frontend domain. If they’re missing, check for HTTPS, correct domain, and that no proxy/middleware is stripping Set-Cookie headers [[source]](https://github.com/better-auth/better-auth/issues/4188). 4. **Cookie settings:** For cross-origin, cookies must have `sameSite: 'none'` and `secure: true`. Both frontend and backend must be served over HTTPS, and your `baseURL` and `trustedOrigins` must match your deployed domains [[source]](https://github.com/better-auth/better-auth/issues/4188). 5. **Explicitly forward cookies:** In Next.js server components, always forward the cookie header from the browser to your auth backend (as you’re doing). If frontend and backend are on different domains, consider proxying session requests through a Next.js API route to keep cookies on the same domain [[source]](https://github.com/better-auth/better-auth/issues/4188). 6. **Next.js 16 caveat:** Make sure you call `cookies()` or `headers()` outside of any cached function and pass the cookie header explicitly to your session retrieval logic. Calling them inside cached functions can cause getSession to return null [[source]](https://github.com/better-auth/better-auth/issues/7008). 7. **Debugging:** Enable debug logging on both frontend and backend. Check actual cookie values and backend logs for validation errors or missing cookies. If you follow these steps and still get null, double-check for any proxy/CDN/middleware that might strip cookies, and ensure your environment variables (like `NEXT_PUBLIC_AUTH_BACKEND_URL` and `BETTER_AUTH_URL`) are set correctly for production. Let me know if you want a minimal config example or have specific debug output! <!-- 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/cb3f4236-846b-42df-ba99-6a0dcb79359d?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/cb3f4236-846b-42df-ba99-6a0dcb79359d?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/cb3f4236-846b-42df-ba99-6a0dcb79359d?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/cb3f4236-846b-42df-ba99-6a0dcb79359d?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/cb3f4236-846b-42df-ba99-6a0dcb79359d?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/cb3f4236-846b-42df-ba99-6a0dcb79359d?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/cb3f4236-846b-42df-ba99-6a0dcb79359d?feedback_type=other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=Your%20issue%20is%20almost%20certainly%20caused%20by%20cookie/session%20handling%20differences%20between%20local%20and%20production%2C%20especially%20with%20cross-origin%20setups%20and%20recent%20Better%20Auth%20versions.%0A%0AHere%E2%80%99s%20what%20you%20need%20to%20do%3A%0A%0A1.%20%2A%2AEnable%20session%20cookie%20cache%3A%2A%2A%20In%20Better%20Auth%20v1.4.x%2B%2C%20you%20must%20set%20%60session.cookieCache.enabled%3A%20true%60%20in%20your%20backend%20config.%20Without%20this%2C%20the%20session_data%20cookie%20isn%E2%80%99t%20set/read%20and%20getSession%20will%20always%20return%20null%20in%20production%20%5B%5Bsource%5D%5D%28https%3A//github.com/better-auth/better-auth/issues/6672%29.%0A%0A2.%20%2A%2ASet%20the%20cookie%20cache%20strategy%3A%2A%2A%20If%20enabling%20cookieCache%20alone%20doesn%E2%80%99t%20fix%20it%2C%20set%20%60session.cookieCache.strategy%3A%20%27jwt%27%60%20%28or%20%60%27base64-hmac%27%60%20if%20you%E2%80%99re%20migrating%20from%20older%20versions%29.%20This%20resolves%20environment-specific%20issues%20for%20many%20users%20%5B%5Bsource%5D%5D%28https%3A//github.com/better-auth/better-auth/issues/7008%29.%0A%0A3.%20%2A%2ACheck%20your%20cookies%20in%20production%3A%2A%2A%20Use%20browser%20dev%20tools%20to%20confirm%20that%20after%20sign-in%2C%20you%20see%20cookies%20like%20%60__Secure-better-auth.session_token%60%20and%20%60__Secure-better-auth.session_data%60%20%28or%20chunked%20variants%29%20set%20for%20your%20frontend%20domain.%20If%20they%E2%80%99re%20missing%2C%20check%20for%20HTTPS%2C%20correct%20domain%2C%20and%20that%20no%20proxy/middleware%20is%20stripping%20Set-Cookie%20headers%20%5B%5Bsource%5D%5D%28https%3A//github.com/better-auth/better-auth/issues/4188%29.%0A%0A4.%20%2A%2ACookie%20settings%3A%2A%2A%20For%20cross-origin%2C%20cookies%20must%20have%20%60sameSite%3A%20%27none%27%60%20and%20%60secure%3A%20true%60.%20Both%20frontend%20and%20backend%20must%20be%20served%20over%20HTTPS%2C%20and%20your%20%60baseURL%60%20and%20%60trustedOrigins%60%20must%20match%20your%20deployed%20domains%20%5B%5Bsource%5D%5D%28https%3A//github.com/better-auth/better-auth/issues/4188%29.%0A%0A5.%20%2A%2AExplicitly%20forward%20cookies%3A%2A%2A%20In%20Next.js%20server%20components%2C%20always%20forward%20the%20cookie%20header%20from%20the%20browser%20to%20your%20auth%20backend%20%28as%20you%E2%80%99re%20doing%29.%20If%20frontend%20and%20backend%20are%20on%20different%20domains%2C%20consider%20proxying%20session%20requests%20through%20a%20Next.js%20API%20route%20to%20keep%20cookies%20on%20the%20same%20domain%20%5B%5Bsource%5D%5D%28https%3A//github.com/better-auth/better-auth/issues/4188%29.%0A%0A6.%20%2A%2ANext.js%2016%20caveat%3A%2A%2A%20Make%20sure%20you%20call%20%60cookies%28%29%60%20or%20%60headers%28%29%60%20outside%20of%20any%20cached%20function%20and%20pass%20the%20cookie%20header%20explicitly%20to%20your%20session%20retrieval%20logic.%20Calling%20them%20inside%20cached%20functions%20can%20cause%20getSession%20to%20return%20null%20%5B%5Bsource%5D%5D%28https%3A//github.com/better-auth/better-auth/issues/7008%29.%0A%0A7.%20%2A%2ADebugging%3A%2A%2A%20Enable%20debug%20logging%20on%20both%20frontend%20and%20backend.%20Check%20actual%20cookie%20values%20and%20backend%20logs%20for%20validation%20errors%20or%20missing%20cookies.%0A%0AIf%20you%20follow%20these%20steps%20and%20still%20get%20null%2C%20double-check%20for%20any%20proxy/CDN/middleware%20that%20might%20strip%20cookies%2C%20and%20ensure%20your%20environment%20variables%20%28like%20%60NEXT_PUBLIC_AUTH_BACKEND_URL%60%20and%20%60BETTER_AUTH_URL%60%29%20are%20set%20correctly%20for%20production.%0A%0ALet%20me%20know%20if%20you%20want%20a%20minimal%20config%20example%20or%20have%20specific%20debug%20output%21)&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/7105)
Author
Owner

@himself65 commented on GitHub (Jan 3, 2026):

Duplicate of #4188. This is definitely related to the cross-domain or subdomain issue.

Possible solution: https://github.com/better-auth/better-auth/issues/4188#issuecomment-3496476832

<!-- gh-comment-id:3706921071 --> @himself65 commented on GitHub (Jan 3, 2026): Duplicate of #4188. This is definitely related to the cross-domain or subdomain issue. Possible solution: https://github.com/better-auth/better-auth/issues/4188#issuecomment-3496476832
Author
Owner

@kuldeepsaini23 commented on GitHub (Jan 3, 2026):

I already tried the above point @dosu @himself65 , I also checked #4188. and tried out that thing also but still getiing null

<!-- gh-comment-id:3706924584 --> @kuldeepsaini23 commented on GitHub (Jan 3, 2026): I already tried the above point @dosu @himself65 , I also checked #4188. and tried out that thing also but still getiing null
Author
Owner

@himself65 commented on GitHub (Jan 3, 2026):

Could you please provider a reproducible repo?

<!-- gh-comment-id:3706925783 --> @himself65 commented on GitHub (Jan 3, 2026): Could you please provider a reproducible repo?
Author
Owner

@kuldeepsaini23 commented on GitHub (Jan 3, 2026):

Actually the error is only reproducible in the production. I try deploying it to Aws Ecs and vercel also, I can add you in the repo if you want

<!-- gh-comment-id:3706926376 --> @kuldeepsaini23 commented on GitHub (Jan 3, 2026): Actually the error is only reproducible in the production. I try deploying it to Aws Ecs and vercel also, I can add you in the repo if you want
Author
Owner

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

You've already covered the standard fixes, so let's dig into advanced causes that often get missed in Hono.js + Next.js + Better Auth production setups:

  1. Your config has session.cookieCache.enabled: false. In Better Auth v1.4.x+, this disables the session_data cookie, which is required for getSession to work in production. Set enabled: true and try strategy: 'jwt' or 'base64-hmac' if you migrated from older versions. This is the most common root cause for persistent null sessions in production, even when everything works locally (reference).

  2. After sign-in, check the browser's Application > Cookies tab and the network response headers for Set-Cookie. You should see both __Secure-better-auth.session_token and __Secure-better-auth.session_data (or chunked variants). If they're missing, the browser won't send them on subsequent requests, and getSession will always return null (reference).

  3. If you use custom Hono routes for auth (e.g., /api/auth/signin), you must use auth.api.signInEmail({ ..., asResponse: true }) and manually forward the Set-Cookie header from the Better Auth response to your client. If you don't, cookies won't be set and sessions will be null (reference).

  4. Some Hono middleware (like hono/language with caching) can overwrite cookies after sign-in. Try disabling cache in such middleware to avoid losing the session cookie (reference).

  5. In Next.js 16, make sure you call cookies() or headers() outside any cached function and pass the cookie header explicitly to your session fetch. Calling them inside cached functions can cause getSession to return null (reference).

  6. If your session payload is large, Better Auth will chunk the session_data cookie. Make sure the entire cookie header (including all chunks) is forwarded to the backend (reference).

If you still get null, please share:

  • The full Set-Cookie headers from your backend after sign-in (in production)
  • A screenshot of browser cookies after login
  • The network trace of your session fetch
  • Any relevant backend logs

Also, clarify: Are frontend and backend on the same domain/subdomain? Is HTTPS enforced everywhere? Any proxies/CDNs/middleware in the request path?

These details will help pinpoint the root cause.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

<!-- gh-comment-id:3706926959 --> @dosubot[bot] commented on GitHub (Jan 3, 2026): <!-- Answer --> You've already covered the standard fixes, so let's dig into advanced causes that often get missed in Hono.js + Next.js + Better Auth production setups: 1. Your config has `session.cookieCache.enabled: false`. In Better Auth v1.4.x+, this disables the `session_data` cookie, which is required for `getSession` to work in production. Set `enabled: true` and try `strategy: 'jwt'` or `'base64-hmac'` if you migrated from older versions. This is the most common root cause for persistent null sessions in production, even when everything works locally ([reference](https://github.com/better-auth/better-auth/issues/7008)). 2. After sign-in, check the browser's Application > Cookies tab and the network response headers for `Set-Cookie`. You should see both `__Secure-better-auth.session_token` and `__Secure-better-auth.session_data` (or chunked variants). If they're missing, the browser won't send them on subsequent requests, and `getSession` will always return null ([reference](https://github.com/better-auth/better-auth/issues/6530)). 3. If you use custom Hono routes for auth (e.g., `/api/auth/signin`), you must use `auth.api.signInEmail({ ..., asResponse: true })` and manually forward the `Set-Cookie` header from the Better Auth response to your client. If you don't, cookies won't be set and sessions will be null ([reference](https://github.com/better-auth/better-auth/issues/6530)). 4. Some Hono middleware (like `hono/language` with caching) can overwrite cookies after sign-in. Try disabling cache in such middleware to avoid losing the session cookie ([reference](https://github.com/better-auth/better-auth/issues/2055)). 5. In Next.js 16, make sure you call `cookies()` or `headers()` outside any cached function and pass the cookie header explicitly to your session fetch. Calling them inside cached functions can cause `getSession` to return null ([reference](https://github.com/better-auth/better-auth/issues/7008)). 6. If your session payload is large, Better Auth will chunk the `session_data` cookie. Make sure the entire cookie header (including all chunks) is forwarded to the backend ([reference](https://github.com/better-auth/better-auth/blob/a4df0d96b676d934caee6071a6b0df7a139b7071/packages/better-auth/src/cookies/session-store.ts#L9-L276)). If you still get null, please share: - The full `Set-Cookie` headers from your backend after sign-in (in production) - A screenshot of browser cookies after login - The network trace of your session fetch - Any relevant backend logs Also, clarify: Are frontend and backend on the same domain/subdomain? Is HTTPS enforced everywhere? Any proxies/CDNs/middleware in the request path? These details will help pinpoint the root cause. <!-- 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/f023f652-d4fc-4141-82e0-f34ed56fcfde?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/f023f652-d4fc-4141-82e0-f34ed56fcfde?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/f023f652-d4fc-4141-82e0-f34ed56fcfde?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/f023f652-d4fc-4141-82e0-f34ed56fcfde?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/f023f652-d4fc-4141-82e0-f34ed56fcfde?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/f023f652-d4fc-4141-82e0-f34ed56fcfde?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/f023f652-d4fc-4141-82e0-f34ed56fcfde?feedback_type=other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=You%27ve%20already%20covered%20the%20standard%20fixes%2C%20so%20let%27s%20dig%20into%20advanced%20causes%20that%20often%20get%20missed%20in%20Hono.js%20%2B%20Next.js%20%2B%20Better%20Auth%20production%20setups%3A%0A%0A1.%20Your%20config%20has%20%60session.cookieCache.enabled%3A%20false%60.%20In%20Better%20Auth%20v1.4.x%2B%2C%20this%20disables%20the%20%60session_data%60%20cookie%2C%20which%20is%20required%20for%20%60getSession%60%20to%20work%20in%20production.%20Set%20%60enabled%3A%20true%60%20and%20try%20%60strategy%3A%20%27jwt%27%60%20or%20%60%27base64-hmac%27%60%20if%20you%20migrated%20from%20older%20versions.%20This%20is%20the%20most%20common%20root%20cause%20for%20persistent%20null%20sessions%20in%20production%2C%20even%20when%20everything%20works%20locally%20%28%5Breference%5D%28https%3A//github.com/better-auth/better-auth/issues/7008%29%29.%0A%0A2.%20After%20sign-in%2C%20check%20the%20browser%27s%20Application%20%3E%20Cookies%20tab%20and%20the%20network%20response%20headers%20for%20%60Set-Cookie%60.%20You%20should%20see%20both%20%60__Secure-better-auth.session_token%60%20and%20%60__Secure-better-auth.session_data%60%20%28or%20chunked%20variants%29.%20If%20they%27re%20missing%2C%20the%20browser%20won%27t%20send%20them%20on%20subsequent%20requests%2C%20and%20%60getSession%60%20will%20always%20return%20null%20%28%5Breference%5D%28https%3A//github.com/better-auth/better-auth/issues/6530%29%29.%0A%0A3.%20If%20you%20use%20custom%20Hono%20routes%20for%20auth%20%28e.g.%2C%20%60/api/auth/signin%60%29%2C%20you%20must%20use%20%60auth.api.signInEmail%28%7B%20...%2C%20asResponse%3A%20true%20%7D%29%60%20and%20manually%20forward%20the%20%60Set-Cookie%60%20header%20from%20the%20Better%20Auth%20response%20to%20your%20client.%20If%20you%20don%27t%2C%20cookies%20won%27t%20be%20set%20and%20sessions%20will%20be%20null%20%28%5Breference%5D%28https%3A//github.com/better-auth/better-auth/issues/6530%29%29.%0A%0A4.%20Some%20Hono%20middleware%20%28like%20%60hono/language%60%20with%20caching%29%20can%20overwrite%20cookies%20after%20sign-in.%20Try%20disabling%20cache%20in%20such%20middleware%20to%20avoid%20losing%20the%20session%20cookie%20%28%5Breference%5D%28https%3A//github.com/better-auth/better-auth/issues/2055%29%29.%0A%0A5.%20In%20Next.js%2016%2C%20make%20sure%20you%20call%20%60cookies%28%29%60%20or%20%60headers%28%29%60%20outside%20any%20cached%20function%20and%20pass%20the%20cookie%20header%20explicitly%20to%20your%20session%20fetch.%20Calling%20them%20inside%20cached%20functions%20can%20cause%20%60getSession%60%20to%20return%20null%20%28%5Breference%5D%28https%3A//github.com/better-auth/better-auth/issues/7008%29%29.%0A%0A6.%20If%20your%20session%20payload%20is%20large%2C%20Better%20Auth%20will%20chunk%20the%20%60session_data%60%20cookie.%20Make%20sure%20the%20entire%20cookie%20header%20%28including%20all%20chunks%29%20is%20forwarded%20to%20the%20backend%20%28%5Breference%5D%28https%3A//github.com/better-auth/better-auth/blob/a4df0d96b676d934caee6071a6b0df7a139b7071/packages/better-auth/src/cookies/session-store.ts%23L9-L276%29%29.%0A%0AIf%20you%20still%20get%20null%2C%20please%20share%3A%0A-%20The%20full%20%60Set-Cookie%60%20headers%20from%20your%20backend%20after%20sign-in%20%28in%20production%29%0A-%20A%20screenshot%20of%20browser%20cookies%20after%20login%0A-%20The%20network%20trace%20of%20your%20session%20fetch%0A-%20Any%20relevant%20backend%20logs%0A%0AAlso%2C%20clarify%3A%20Are%20frontend%20and%20backend%20on%20the%20same%20domain/subdomain%3F%20Is%20HTTPS%20enforced%20everywhere%3F%20Any%20proxies/CDNs/middleware%20in%20the%20request%20path%3F%0A%0AThese%20details%20will%20help%20pinpoint%20the%20root%20cause.)&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/7105)
Author
Owner

@kuldeepsaini23 commented on GitHub (Jan 3, 2026):

@dosu

Image
<!-- gh-comment-id:3706952701 --> @kuldeepsaini23 commented on GitHub (Jan 3, 2026): @dosu <img width="911" height="601" alt="Image" src="https://github.com/user-attachments/assets/0393ead9-e97d-45eb-aed7-4f10f57c331a" />
Author
Owner

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

Based on your config and the screenshot description, your main issue is that session cookies required by Better Auth—specifically __Secure-better-auth.session_token and __Secure-better-auth.session_data—are either missing or misconfigured in production. With session.cookieCache.enabled: false, the session_data cookie is never set, so getSession will always return null in production, even if other cookies are present (source).

To fix this, update your Better Auth backend config to:

session: {
  cookieCache: {
    enabled: true,
    strategy: 'jwt', // or 'base64-hmac' if you migrated from older versions
    maxAge: 10 * 60,
  },
},

After deploying this change, sign in again and check the browser's cookies for both __Secure-better-auth.session_token and __Secure-better-auth.session_data (or chunked variants like __Secure-better-auth.session_data.0). Both must have Secure and SameSite=None, and be set for your frontend domain (source). If you still get null, check the network response headers after sign-in for Set-Cookie and ensure no proxy or middleware is stripping them.

If you can, please paste the exact cookie names and attributes from your browser after login, and the Set-Cookie headers from your backend’s sign-in response. This will help confirm if the cookies are being set and scoped correctly.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

<!-- gh-comment-id:3706956313 --> @dosubot[bot] commented on GitHub (Jan 3, 2026): <!-- Answer --> Based on your config and the screenshot description, your main issue is that session cookies required by Better Auth—specifically __Secure-better-auth.session_token and __Secure-better-auth.session_data—are either missing or misconfigured in production. With session.cookieCache.enabled: false, the session_data cookie is never set, so getSession will always return null in production, even if other cookies are present ([source](https://github.com/better-auth/better-auth/issues/6672)). To fix this, update your Better Auth backend config to: ```js session: { cookieCache: { enabled: true, strategy: 'jwt', // or 'base64-hmac' if you migrated from older versions maxAge: 10 * 60, }, }, ``` After deploying this change, sign in again and check the browser's cookies for both __Secure-better-auth.session_token and __Secure-better-auth.session_data (or chunked variants like __Secure-better-auth.session_data.0). Both must have Secure and SameSite=None, and be set for your frontend domain ([source](https://github.com/better-auth/better-auth/issues/6530)). If you still get null, check the network response headers after sign-in for Set-Cookie and ensure no proxy or middleware is stripping them. If you can, please paste the exact cookie names and attributes from your browser after login, and the Set-Cookie headers from your backend’s sign-in response. This will help confirm if the cookies are being set and scoped correctly. <!-- 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/c79f578f-8af2-4655-8525-87626a219f3a?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/c79f578f-8af2-4655-8525-87626a219f3a?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/c79f578f-8af2-4655-8525-87626a219f3a?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/c79f578f-8af2-4655-8525-87626a219f3a?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/c79f578f-8af2-4655-8525-87626a219f3a?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/c79f578f-8af2-4655-8525-87626a219f3a?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/c79f578f-8af2-4655-8525-87626a219f3a?feedback_type=other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=Based%20on%20your%20config%20and%20the%20screenshot%20description%2C%20your%20main%20issue%20is%20that%20session%20cookies%20required%20by%20Better%20Auth%E2%80%94specifically%20__Secure-better-auth.session_token%20and%20__Secure-better-auth.session_data%E2%80%94are%20either%20missing%20or%20misconfigured%20in%20production.%20With%20session.cookieCache.enabled%3A%20false%2C%20the%20session_data%20cookie%20is%20never%20set%2C%20so%20getSession%20will%20always%20return%20null%20in%20production%2C%20even%20if%20other%20cookies%20are%20present%20%28%5Bsource%5D%28https%3A//github.com/better-auth/better-auth/issues/6672%29%29.%0A%0ATo%20fix%20this%2C%20update%20your%20Better%20Auth%20backend%20config%20to%3A%0A%0A%60%60%60js%0Asession%3A%20%7B%0A%20%20cookieCache%3A%20%7B%0A%20%20%20%20enabled%3A%20true%2C%0A%20%20%20%20strategy%3A%20%27jwt%27%2C%20//%20or%20%27base64-hmac%27%20if%20you%20migrated%20from%20older%20versions%0A%20%20%20%20maxAge%3A%2010%20%2A%2060%2C%0A%20%20%7D%2C%0A%7D%2C%0A%60%60%60%0A%0AAfter%20deploying%20this%20change%2C%20sign%20in%20again%20and%20check%20the%20browser%27s%20cookies%20for%20both%20__Secure-better-auth.session_token%20and%20__Secure-better-auth.session_data%20%28or%20chunked%20variants%20like%20__Secure-better-auth.session_data.0%29.%20Both%20must%20have%20Secure%20and%20SameSite%3DNone%2C%20and%20be%20set%20for%20your%20frontend%20domain%20%28%5Bsource%5D%28https%3A//github.com/better-auth/better-auth/issues/6530%29%29.%20If%20you%20still%20get%20null%2C%20check%20the%20network%20response%20headers%20after%20sign-in%20for%20Set-Cookie%20and%20ensure%20no%20proxy%20or%20middleware%20is%20stripping%20them.%0A%0AIf%20you%20can%2C%20please%20paste%20the%20exact%20cookie%20names%20and%20attributes%20from%20your%20browser%20after%20login%2C%20and%20the%20Set-Cookie%20headers%20from%20your%20backend%E2%80%99s%20sign-in%20response.%20This%20will%20help%20confirm%20if%20the%20cookies%20are%20being%20set%20and%20scoped%20correctly.)&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/7105)
Author
Owner

@kuldeepsaini23 commented on GitHub (Jan 3, 2026):

session: {
cookieCache: {
enabled: true,
strategy: 'jwt', // or 'base64-hmac' if you migrated from older versions
maxAge: 10 * 60,
},
},
@dosu I already tried that

<!-- gh-comment-id:3706959720 --> @kuldeepsaini23 commented on GitHub (Jan 3, 2026): session: { cookieCache: { enabled: true, strategy: 'jwt', // or 'base64-hmac' if you migrated from older versions maxAge: 10 * 60, }, }, @dosu I already tried that
Author
Owner

@kuldeepsaini23 commented on GitHub (Jan 3, 2026):

@himself65 May ia dd you in my repo

<!-- gh-comment-id:3706960993 --> @kuldeepsaini23 commented on GitHub (Jan 3, 2026): @himself65 May ia dd you in my repo
Author
Owner

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

Since you’ve already enabled session.cookieCache with strategy: 'jwt' and still get null sessions in production, let’s dig into advanced causes that often get missed:

  1. Double-check that after sign-in, your browser has both __Secure-better-auth.session_token and __Secure-better-auth.session_data (or chunked variants like .session_data.0, .session_data.1) set for your frontend domain, with Secure and SameSite=None attributes. If any are missing, session retrieval will fail—even if other cookies are present. Large session payloads can cause chunking, and missing a chunk will break the session. See code details

  2. Check the network tab after sign-in for the backend’s Set-Cookie headers. If these aren’t present or are stripped by a proxy, CDN, or middleware, the browser won’t store the session cookies and getSession will always return null. See issue

  3. If you use custom Hono routes for auth (like /api/auth/signin), you must use asResponse: true and manually forward the Set-Cookie header from the Better Auth response to your client. Otherwise, cookies won’t be set. See example

  4. In Next.js 16, make sure you call cookies() or headers() outside any cached function and pass the cookie header explicitly to your session fetch. Calling them inside cached functions can cause getSession to return null. See issue

  5. If your frontend and backend are on different domains or subdomains, confirm that both are served over HTTPS, and that your baseURL, trustedOrigins, and CORS settings match your deployed domains. See issue

To help pinpoint the root cause, please provide:

  • The exact list of cookies (names, values, attributes) present in the browser after login in production
  • The Set-Cookie headers from your backend after sign-in
  • The network trace of your session fetch request
  • Your deployment topology (are frontend and backend on the same domain, subdomain, or cross-domain? Any proxies/CDNs/middleware in the path?)

With this info, we can identify if it’s a chunking, cookie, or proxy issue and recommend a targeted fix.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

<!-- gh-comment-id:3706961437 --> @dosubot[bot] commented on GitHub (Jan 3, 2026): <!-- Answer --> Since you’ve already enabled `session.cookieCache` with `strategy: 'jwt'` and still get null sessions in production, let’s dig into advanced causes that often get missed: 1. Double-check that after sign-in, your browser has both `__Secure-better-auth.session_token` and `__Secure-better-auth.session_data` (or chunked variants like `.session_data.0`, `.session_data.1`) set for your frontend domain, with `Secure` and `SameSite=None` attributes. If any are missing, session retrieval will fail—even if other cookies are present. Large session payloads can cause chunking, and missing a chunk will break the session. [See code details](https://github.com/better-auth/better-auth/blob/a4df0d96b676d934caee6071a6b0df7a139b7071/packages/better-auth/src/cookies/session-store.ts#L9-L276) 2. Check the network tab after sign-in for the backend’s `Set-Cookie` headers. If these aren’t present or are stripped by a proxy, CDN, or middleware, the browser won’t store the session cookies and `getSession` will always return null. [See issue](https://github.com/better-auth/better-auth/issues/6530) 3. If you use custom Hono routes for auth (like `/api/auth/signin`), you must use `asResponse: true` and manually forward the `Set-Cookie` header from the Better Auth response to your client. Otherwise, cookies won’t be set. [See example](https://github.com/better-auth/better-auth/issues/6530) 4. In Next.js 16, make sure you call `cookies()` or `headers()` outside any cached function and pass the cookie header explicitly to your session fetch. Calling them inside cached functions can cause `getSession` to return null. [See issue](https://github.com/better-auth/better-auth/issues/7008) 5. If your frontend and backend are on different domains or subdomains, confirm that both are served over HTTPS, and that your `baseURL`, `trustedOrigins`, and CORS settings match your deployed domains. [See issue](https://github.com/better-auth/better-auth/issues/4188) To help pinpoint the root cause, please provide: - The exact list of cookies (names, values, attributes) present in the browser after login in production - The `Set-Cookie` headers from your backend after sign-in - The network trace of your session fetch request - Your deployment topology (are frontend and backend on the same domain, subdomain, or cross-domain? Any proxies/CDNs/middleware in the path?) With this info, we can identify if it’s a chunking, cookie, or proxy issue and recommend a targeted fix. <!-- 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/5258dcec-9a3c-4566-a56c-784e61ea60e1?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/5258dcec-9a3c-4566-a56c-784e61ea60e1?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/5258dcec-9a3c-4566-a56c-784e61ea60e1?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/5258dcec-9a3c-4566-a56c-784e61ea60e1?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/5258dcec-9a3c-4566-a56c-784e61ea60e1?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/5258dcec-9a3c-4566-a56c-784e61ea60e1?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/5258dcec-9a3c-4566-a56c-784e61ea60e1?feedback_type=other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=Since%20you%E2%80%99ve%20already%20enabled%20%60session.cookieCache%60%20with%20%60strategy%3A%20%27jwt%27%60%20and%20still%20get%20null%20sessions%20in%20production%2C%20let%E2%80%99s%20dig%20into%20advanced%20causes%20that%20often%20get%20missed%3A%0A%0A1.%20Double-check%20that%20after%20sign-in%2C%20your%20browser%20has%20both%20%60__Secure-better-auth.session_token%60%20and%20%60__Secure-better-auth.session_data%60%20%28or%20chunked%20variants%20like%20%60.session_data.0%60%2C%20%60.session_data.1%60%29%20set%20for%20your%20frontend%20domain%2C%20with%20%60Secure%60%20and%20%60SameSite%3DNone%60%20attributes.%20If%20any%20are%20missing%2C%20session%20retrieval%20will%20fail%E2%80%94even%20if%20other%20cookies%20are%20present.%20Large%20session%20payloads%20can%20cause%20chunking%2C%20and%20missing%20a%20chunk%20will%20break%20the%20session.%20%5BSee%20code%20details%5D%28https%3A//github.com/better-auth/better-auth/blob/a4df0d96b676d934caee6071a6b0df7a139b7071/packages/better-auth/src/cookies/session-store.ts%23L9-L276%29%0A%0A2.%20Check%20the%20network%20tab%20after%20sign-in%20for%20the%20backend%E2%80%99s%20%60Set-Cookie%60%20headers.%20If%20these%20aren%E2%80%99t%20present%20or%20are%20stripped%20by%20a%20proxy%2C%20CDN%2C%20or%20middleware%2C%20the%20browser%20won%E2%80%99t%20store%20the%20session%20cookies%20and%20%60getSession%60%20will%20always%20return%20null.%20%5BSee%20issue%5D%28https%3A//github.com/better-auth/better-auth/issues/6530%29%0A%0A3.%20If%20you%20use%20custom%20Hono%20routes%20for%20auth%20%28like%20%60/api/auth/signin%60%29%2C%20you%20must%20use%20%60asResponse%3A%20true%60%20and%20manually%20forward%20the%20%60Set-Cookie%60%20header%20from%20the%20Better%20Auth%20response%20to%20your%20client.%20Otherwise%2C%20cookies%20won%E2%80%99t%20be%20set.%20%5BSee%20example%5D%28https%3A//github.com/better-auth/better-auth/issues/6530%29%0A%0A4.%20In%20Next.js%2016%2C%20make%20sure%20you%20call%20%60cookies%28%29%60%20or%20%60headers%28%29%60%20outside%20any%20cached%20function%20and%20pass%20the%20cookie%20header%20explicitly%20to%20your%20session%20fetch.%20Calling%20them%20inside%20cached%20functions%20can%20cause%20%60getSession%60%20to%20return%20null.%20%5BSee%20issue%5D%28https%3A//github.com/better-auth/better-auth/issues/7008%29%0A%0A5.%20If%20your%20frontend%20and%20backend%20are%20on%20different%20domains%20or%20subdomains%2C%20confirm%20that%20both%20are%20served%20over%20HTTPS%2C%20and%20that%20your%20%60baseURL%60%2C%20%60trustedOrigins%60%2C%20and%20CORS%20settings%20match%20your%20deployed%20domains.%20%5BSee%20issue%5D%28https%3A//github.com/better-auth/better-auth/issues/4188%29%0A%0ATo%20help%20pinpoint%20the%20root%20cause%2C%20please%20provide%3A%0A-%20The%20exact%20list%20of%20cookies%20%28names%2C%20values%2C%20attributes%29%20present%20in%20the%20browser%20after%20login%20in%20production%0A-%20The%20%60Set-Cookie%60%20headers%20from%20your%20backend%20after%20sign-in%0A-%20The%20network%20trace%20of%20your%20session%20fetch%20request%0A-%20Your%20deployment%20topology%20%28are%20frontend%20and%20backend%20on%20the%20same%20domain%2C%20subdomain%2C%20or%20cross-domain%3F%20Any%20proxies/CDNs/middleware%20in%20the%20path%3F%29%0A%0AWith%20this%20info%2C%20we%20can%20identify%20if%20it%E2%80%99s%20a%20chunking%2C%20cookie%2C%20or%20proxy%20issue%20and%20recommend%20a%20targeted%20fix.)&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/7105)
Author
Owner

@kuldeepsaini23 commented on GitHub (Jan 3, 2026):

What I notice was My frontend is not able to send the cookies to my backend

<!-- gh-comment-id:3706969625 --> @kuldeepsaini23 commented on GitHub (Jan 3, 2026): What I notice was My frontend is not able to send the cookies to my backend
Author
Owner

@kuldeepsaini23 commented on GitHub (Jan 3, 2026):

@dosu I am getting the code mismatch advanced: {
defaultCookieAttributes: {
sameSite: 'none',
secure: true,
partitioned: true,
},
}, with this I don't know why

<!-- gh-comment-id:3706972326 --> @kuldeepsaini23 commented on GitHub (Jan 3, 2026): @dosu I am getting the code mismatch advanced: { defaultCookieAttributes: { sameSite: 'none', secure: true, partitioned: true, }, }, with this I don't know why
Author
Owner

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

The "code mismatch" error and your session issues are almost certainly caused by setting partitioned: true in your defaultCookieAttributes. The partitioned attribute is a new browser feature that can cause cookies to be siloed and not sent across domains, which breaks OAuth and session flows in cross-domain setups—even if everything works locally. This is a known issue in Better Auth and other frameworks: removing partitioned: true usually resolves code mismatch and null session errors in production (see #6645, see #4044).

Better Auth does not validate or handle partitioned server-side; it just passes the attribute to the browser. If your browser, CDN, or proxy doesn't fully support partitioned cookies, or if your frontend/backend are on different domains, the session cookies won't be sent and you'll get code mismatch or null session errors (see #6645).

To fix this, remove partitioned: true from your config and redeploy. Your config should look like:

advanced: {
  defaultCookieAttributes: {
    sameSite: 'none',
    secure: true,
    // partitioned: true, // REMOVE THIS LINE
  },
}

If you need cross-domain auth, the best practice is to use subdomains of the same root domain (e.g., app.example.com and api.example.com) and enable crossSubDomainCookies with domain: '.example.com'. If you must use different domains, proxy your auth API calls through a Next.js API route to keep cookies on the same domain (see workaround).

If you still see errors after removing partitioned: true, please share your exact frontend/backend domains and any proxies/CDNs in the path, plus the full error message or stack trace.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

<!-- gh-comment-id:3706974552 --> @dosubot[bot] commented on GitHub (Jan 3, 2026): <!-- Answer --> The "code mismatch" error and your session issues are almost certainly caused by setting partitioned: true in your defaultCookieAttributes. The partitioned attribute is a new browser feature that can cause cookies to be siloed and not sent across domains, which breaks OAuth and session flows in cross-domain setups—even if everything works locally. This is a known issue in Better Auth and other frameworks: removing partitioned: true usually resolves code mismatch and null session errors in production ([see #6645](https://github.com/better-auth/better-auth/issues/6645), [see #4044](https://github.com/better-auth/better-auth/issues/4044)). Better Auth does not validate or handle partitioned server-side; it just passes the attribute to the browser. If your browser, CDN, or proxy doesn't fully support partitioned cookies, or if your frontend/backend are on different domains, the session cookies won't be sent and you'll get code mismatch or null session errors ([see #6645](https://github.com/better-auth/better-auth/issues/6645)). To fix this, remove partitioned: true from your config and redeploy. Your config should look like: ```js advanced: { defaultCookieAttributes: { sameSite: 'none', secure: true, // partitioned: true, // REMOVE THIS LINE }, } ``` If you need cross-domain auth, the best practice is to use subdomains of the same root domain (e.g., app.example.com and api.example.com) and enable crossSubDomainCookies with domain: '.example.com'. If you must use different domains, proxy your auth API calls through a Next.js API route to keep cookies on the same domain ([see workaround](https://github.com/better-auth/better-auth/issues/4044)). If you still see errors after removing partitioned: true, please share your exact frontend/backend domains and any proxies/CDNs in the path, plus the full error message or stack trace. <!-- 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/93fca287-a461-4ef9-be92-62e8d7c77688?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/93fca287-a461-4ef9-be92-62e8d7c77688?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/93fca287-a461-4ef9-be92-62e8d7c77688?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/93fca287-a461-4ef9-be92-62e8d7c77688?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/93fca287-a461-4ef9-be92-62e8d7c77688?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/93fca287-a461-4ef9-be92-62e8d7c77688?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/93fca287-a461-4ef9-be92-62e8d7c77688?feedback_type=other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=The%20%22code%20mismatch%22%20error%20and%20your%20session%20issues%20are%20almost%20certainly%20caused%20by%20setting%20partitioned%3A%20true%20in%20your%20defaultCookieAttributes.%20The%20partitioned%20attribute%20is%20a%20new%20browser%20feature%20that%20can%20cause%20cookies%20to%20be%20siloed%20and%20not%20sent%20across%20domains%2C%20which%20breaks%20OAuth%20and%20session%20flows%20in%20cross-domain%20setups%E2%80%94even%20if%20everything%20works%20locally.%20This%20is%20a%20known%20issue%20in%20Better%20Auth%20and%20other%20frameworks%3A%20removing%20partitioned%3A%20true%20usually%20resolves%20code%20mismatch%20and%20null%20session%20errors%20in%20production%20%28%5Bsee%20%236645%5D%28https%3A//github.com/better-auth/better-auth/issues/6645%29%2C%20%5Bsee%20%234044%5D%28https%3A//github.com/better-auth/better-auth/issues/4044%29%29.%0A%0ABetter%20Auth%20does%20not%20validate%20or%20handle%20partitioned%20server-side%3B%20it%20just%20passes%20the%20attribute%20to%20the%20browser.%20If%20your%20browser%2C%20CDN%2C%20or%20proxy%20doesn%27t%20fully%20support%20partitioned%20cookies%2C%20or%20if%20your%20frontend/backend%20are%20on%20different%20domains%2C%20the%20session%20cookies%20won%27t%20be%20sent%20and%20you%27ll%20get%20code%20mismatch%20or%20null%20session%20errors%20%28%5Bsee%20%236645%5D%28https%3A//github.com/better-auth/better-auth/issues/6645%29%29.%0A%0ATo%20fix%20this%2C%20remove%20partitioned%3A%20true%20from%20your%20config%20and%20redeploy.%20Your%20config%20should%20look%20like%3A%0A%0A%60%60%60js%0Aadvanced%3A%20%7B%0A%20%20defaultCookieAttributes%3A%20%7B%0A%20%20%20%20sameSite%3A%20%27none%27%2C%0A%20%20%20%20secure%3A%20true%2C%0A%20%20%20%20//%20partitioned%3A%20true%2C%20//%20REMOVE%20THIS%20LINE%0A%20%20%7D%2C%0A%7D%0A%60%60%60%0A%0AIf%20you%20need%20cross-domain%20auth%2C%20the%20best%20practice%20is%20to%20use%20subdomains%20of%20the%20same%20root%20domain%20%28e.g.%2C%20app.example.com%20and%20api.example.com%29%20and%20enable%20crossSubDomainCookies%20with%20domain%3A%20%27.example.com%27.%20If%20you%20must%20use%20different%20domains%2C%20proxy%20your%20auth%20API%20calls%20through%20a%20Next.js%20API%20route%20to%20keep%20cookies%20on%20the%20same%20domain%20%28%5Bsee%20workaround%5D%28https%3A//github.com/better-auth/better-auth/issues/4044%29%29.%0A%0AIf%20you%20still%20see%20errors%20after%20removing%20partitioned%3A%20true%2C%20please%20share%20your%20exact%20frontend/backend%20domains%20and%20any%20proxies/CDNs%20in%20the%20path%2C%20plus%20the%20full%20error%20message%20or%20stack%20trace.)&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/7105)
Author
Owner

@kuldeepsaini23 commented on GitHub (Jan 3, 2026):

@dosu
advanced: {
defaultCookieAttributes: {
sameSite: 'none',
secure: true,
// partitioned: true, // REMOVE THIS LINE
},
}
tried this but still getting mismatch error

<!-- gh-comment-id:3707074468 --> @kuldeepsaini23 commented on GitHub (Jan 3, 2026): @dosu advanced: { defaultCookieAttributes: { sameSite: 'none', secure: true, // partitioned: true, // REMOVE THIS LINE }, } tried this but still getting mismatch error
Author
Owner

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

If you’re still getting a code mismatch error after removing partitioned: true, the root cause is almost always a cookie or OAuth state issue in production—especially with cross-domain or proxy setups.

Here’s what to check next:

  1. Make sure your advanced.cookies.state config explicitly sets sameSite: 'none', secure: true, and (if using subdomains) domain: '.yourdomain.com'. This ensures the OAuth state cookie is sent on POST callbacks, which is critical for OAuth flows like Google or Apple sign-in. Example:

    advanced: {
      cookies: {
        state: {
          attributes: {
            sameSite: 'none',
            secure: true,
            domain: '.yourdomain.com', // match your root domain, no protocol
          },
        },
      },
    }
    

    Reference

  2. If you’re using subdomains, enable crossSubDomainCookies with the root domain:

    advanced: {
      crossSubDomainCookies: {
        enabled: true,
        domain: '.yourdomain.com',
      },
    }
    

    Reference

  3. Clear all old/stale cookies in your browser before retrying the OAuth flow. Stale cookies are a common cause of state/code mismatch errors, especially after config changes. Reference

  4. Double-check that your frontend and backend are both using HTTPS, and that your trustedOrigins and CORS settings exactly match your frontend’s production URL. Reference

  5. If you’re behind a proxy/CDN (like Vercel, Cloudflare, or AWS Gateway), make sure Set-Cookie and Cookie headers are not being stripped or rewritten. Reference

  6. If frontend and backend are on different domains, proxy all auth/session API calls through a Next.js API route so requests originate from the same domain. This is the most reliable fix for persistent null sessions or code mismatch in cross-domain setups. Reference

  7. If you’re on Next.js 16, call cookies() or headers() outside any cached function and pass the cookie header explicitly to your session retrieval logic. Reference

If you still see the error, please share your exact frontend/backend domains, any proxies/CDNs in the path, and the Set-Cookie headers from your backend after sign-in. This will help pinpoint any remaining misconfigurations.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

<!-- gh-comment-id:3707077032 --> @dosubot[bot] commented on GitHub (Jan 3, 2026): <!-- Answer --> If you’re still getting a code mismatch error after removing partitioned: true, the root cause is almost always a cookie or OAuth state issue in production—especially with cross-domain or proxy setups. Here’s what to check next: 1. Make sure your advanced.cookies.state config explicitly sets sameSite: 'none', secure: true, and (if using subdomains) domain: '.yourdomain.com'. This ensures the OAuth state cookie is sent on POST callbacks, which is critical for OAuth flows like Google or Apple sign-in. Example: ```js advanced: { cookies: { state: { attributes: { sameSite: 'none', secure: true, domain: '.yourdomain.com', // match your root domain, no protocol }, }, }, } ``` [Reference](https://github.com/better-auth/better-auth/issues/5243) 2. If you’re using subdomains, enable crossSubDomainCookies with the root domain: ```js advanced: { crossSubDomainCookies: { enabled: true, domain: '.yourdomain.com', }, } ``` [Reference](https://github.com/better-auth/better-auth/issues/3938) 3. Clear all old/stale cookies in your browser before retrying the OAuth flow. Stale cookies are a common cause of state/code mismatch errors, especially after config changes. [Reference](https://github.com/better-auth/better-auth/issues/2157) 4. Double-check that your frontend and backend are both using HTTPS, and that your trustedOrigins and CORS settings exactly match your frontend’s production URL. [Reference](https://github.com/better-auth/better-auth/issues/3938) 5. If you’re behind a proxy/CDN (like Vercel, Cloudflare, or AWS Gateway), make sure Set-Cookie and Cookie headers are not being stripped or rewritten. [Reference](https://github.com/better-auth/better-auth/issues/3938) 6. If frontend and backend are on different domains, proxy all auth/session API calls through a Next.js API route so requests originate from the same domain. This is the most reliable fix for persistent null sessions or code mismatch in cross-domain setups. [Reference](https://github.com/better-auth/better-auth/issues/4044) 7. If you’re on Next.js 16, call cookies() or headers() outside any cached function and pass the cookie header explicitly to your session retrieval logic. [Reference](https://github.com/better-auth/better-auth/issues/7008) If you still see the error, please share your exact frontend/backend domains, any proxies/CDNs in the path, and the Set-Cookie headers from your backend after sign-in. This will help pinpoint any remaining misconfigurations. <!-- 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/5838cde9-0230-41d3-b933-cf3411eb9ea2?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/5838cde9-0230-41d3-b933-cf3411eb9ea2?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/5838cde9-0230-41d3-b933-cf3411eb9ea2?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/5838cde9-0230-41d3-b933-cf3411eb9ea2?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/5838cde9-0230-41d3-b933-cf3411eb9ea2?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/5838cde9-0230-41d3-b933-cf3411eb9ea2?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/5838cde9-0230-41d3-b933-cf3411eb9ea2?feedback_type=other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=If%20you%E2%80%99re%20still%20getting%20a%20code%20mismatch%20error%20after%20removing%20partitioned%3A%20true%2C%20the%20root%20cause%20is%20almost%20always%20a%20cookie%20or%20OAuth%20state%20issue%20in%20production%E2%80%94especially%20with%20cross-domain%20or%20proxy%20setups.%0A%0AHere%E2%80%99s%20what%20to%20check%20next%3A%0A%0A1.%20Make%20sure%20your%20advanced.cookies.state%20config%20explicitly%20sets%20sameSite%3A%20%27none%27%2C%20secure%3A%20true%2C%20and%20%28if%20using%20subdomains%29%20domain%3A%20%27.yourdomain.com%27.%20This%20ensures%20the%20OAuth%20state%20cookie%20is%20sent%20on%20POST%20callbacks%2C%20which%20is%20critical%20for%20OAuth%20flows%20like%20Google%20or%20Apple%20sign-in.%20Example%3A%0A%20%20%20%60%60%60js%0A%20%20%20advanced%3A%20%7B%0A%20%20%20%20%20cookies%3A%20%7B%0A%20%20%20%20%20%20%20state%3A%20%7B%0A%20%20%20%20%20%20%20%20%20attributes%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20sameSite%3A%20%27none%27%2C%0A%20%20%20%20%20%20%20%20%20%20%20secure%3A%20true%2C%0A%20%20%20%20%20%20%20%20%20%20%20domain%3A%20%27.yourdomain.com%27%2C%20//%20match%20your%20root%20domain%2C%20no%20protocol%0A%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%7D%2C%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%20%20%20%5BReference%5D%28https%3A//github.com/better-auth/better-auth/issues/5243%29%0A%0A2.%20If%20you%E2%80%99re%20using%20subdomains%2C%20enable%20crossSubDomainCookies%20with%20the%20root%20domain%3A%0A%20%20%20%60%60%60js%0A%20%20%20advanced%3A%20%7B%0A%20%20%20%20%20crossSubDomainCookies%3A%20%7B%0A%20%20%20%20%20%20%20enabled%3A%20true%2C%0A%20%20%20%20%20%20%20domain%3A%20%27.yourdomain.com%27%2C%0A%20%20%20%20%20%7D%2C%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%20%20%20%5BReference%5D%28https%3A//github.com/better-auth/better-auth/issues/3938%29%0A%0A3.%20Clear%20all%20old/stale%20cookies%20in%20your%20browser%20before%20retrying%20the%20OAuth%20flow.%20Stale%20cookies%20are%20a%20common%20cause%20of%20state/code%20mismatch%20errors%2C%20especially%20after%20config%20changes.%20%5BReference%5D%28https%3A//github.com/better-auth/better-auth/issues/2157%29%0A%0A4.%20Double-check%20that%20your%20frontend%20and%20backend%20are%20both%20using%20HTTPS%2C%20and%20that%20your%20trustedOrigins%20and%20CORS%20settings%20exactly%20match%20your%20frontend%E2%80%99s%20production%20URL.%20%5BReference%5D%28https%3A//github.com/better-auth/better-auth/issues/3938%29%0A%0A5.%20If%20you%E2%80%99re%20behind%20a%20proxy/CDN%20%28like%20Vercel%2C%20Cloudflare%2C%20or%20AWS%20Gateway%29%2C%20make%20sure%20Set-Cookie%20and%20Cookie%20headers%20are%20not%20being%20stripped%20or%20rewritten.%20%5BReference%5D%28https%3A//github.com/better-auth/better-auth/issues/3938%29%0A%0A6.%20If%20frontend%20and%20backend%20are%20on%20different%20domains%2C%20proxy%20all%20auth/session%20API%20calls%20through%20a%20Next.js%20API%20route%20so%20requests%20originate%20from%20the%20same%20domain.%20This%20is%20the%20most%20reliable%20fix%20for%20persistent%20null%20sessions%20or%20code%20mismatch%20in%20cross-domain%20setups.%20%5BReference%5D%28https%3A//github.com/better-auth/better-auth/issues/4044%29%0A%0A7.%20If%20you%E2%80%99re%20on%20Next.js%2016%2C%20call%20cookies%28%29%20or%20headers%28%29%20outside%20any%20cached%20function%20and%20pass%20the%20cookie%20header%20explicitly%20to%20your%20session%20retrieval%20logic.%20%5BReference%5D%28https%3A//github.com/better-auth/better-auth/issues/7008%29%0A%0AIf%20you%20still%20see%20the%20error%2C%20please%20share%20your%20exact%20frontend/backend%20domains%2C%20any%20proxies/CDNs%20in%20the%20path%2C%20and%20the%20Set-Cookie%20headers%20from%20your%20backend%20after%20sign-in.%20This%20will%20help%20pinpoint%20any%20remaining%20misconfigurations.)&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/7105)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#10729