[GH-ISSUE #2143] APIError: Failed to get session #9066

Closed
opened 2026-04-13 04:21:39 -05:00 by GiteaMirror · 12 comments
Owner

Originally created by @sovetski on GitHub (Apr 5, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/2143

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

I am using the latest version of nextjs and better auth, I followed these instructions: https://www.better-auth.com/docs/integrations/next#create-api-route

Current vs. Expected behavior

When I log in successfully, after redirecting to the home page, it says "APIError: Failed to get session"

I should be able to login without this error

What version of Better Auth are you using?

1.2.5

Provide environment information

- OS: Linux, Ubuntu 24

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

Backend, Client, Documentation, Package

Auth config (if applicable)

import { betterAuth } from "better-auth";
import { prismaAdapter } from "better-auth/adapters/prisma";
import { PrismaClient } from "@packages/prisma";
import { username, admin } from "better-auth/plugins";

const prisma = new PrismaClient();

export const auth = betterAuth({
    plugins: [username(), admin()],
    emailAndPassword: {
        enabled: true,
    },
    database: prismaAdapter(prisma, {
        provider: "mysql",
    }),
});

Additional context

My middleware:

import { NextRequest, NextResponse } from "next/server";
import { headers } from "next/headers";
import { auth } from "@lib/auth";

export async function middleware(request: NextRequest) {
    const session = await auth.api.getSession({
        headers: await headers(),
    });

    if (!session) {
        return NextResponse.redirect(new URL("/login", request.url));
    }

    return NextResponse.next();
}

export const config = {
    runtime: "nodejs",
    matcher: ["/"],
};

I am using this to login:

                await authClient.signIn.username(
                    {
                        username: data.username,
                        password: data.password,
                    },
                    {
                        onSuccess,
                        onError,
                    },
                );

            const onSuccess = () => {
                router.push("/");
            };
Originally created by @sovetski on GitHub (Apr 5, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/2143 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce I am using the latest version of nextjs and better auth, I followed these instructions: https://www.better-auth.com/docs/integrations/next#create-api-route ### Current vs. Expected behavior When I log in successfully, after redirecting to the home page, it says "APIError: Failed to get session" I should be able to login without this error ### What version of Better Auth are you using? 1.2.5 ### Provide environment information ```bash - OS: Linux, Ubuntu 24 ``` ### Which area(s) are affected? (Select all that apply) Backend, Client, Documentation, Package ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth"; import { prismaAdapter } from "better-auth/adapters/prisma"; import { PrismaClient } from "@packages/prisma"; import { username, admin } from "better-auth/plugins"; const prisma = new PrismaClient(); export const auth = betterAuth({ plugins: [username(), admin()], emailAndPassword: { enabled: true, }, database: prismaAdapter(prisma, { provider: "mysql", }), }); ``` ### Additional context My middleware: ```ts import { NextRequest, NextResponse } from "next/server"; import { headers } from "next/headers"; import { auth } from "@lib/auth"; export async function middleware(request: NextRequest) { const session = await auth.api.getSession({ headers: await headers(), }); if (!session) { return NextResponse.redirect(new URL("/login", request.url)); } return NextResponse.next(); } export const config = { runtime: "nodejs", matcher: ["/"], }; ``` I am using this to login: ```ts await authClient.signIn.username( { username: data.username, password: data.password, }, { onSuccess, onError, }, ); const onSuccess = () => { router.push("/"); }; ```
GiteaMirror added the locked label 2026-04-13 04:21:39 -05:00
Author
Owner

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

refer to this - https://www.better-auth.com/docs/integrations/next#middleware

<!-- gh-comment-id:2781116758 --> @Kinfe123 commented on GitHub (Apr 5, 2025): refer to this - https://www.better-auth.com/docs/integrations/next#middleware
Author
Owner

@sovetski commented on GitHub (Apr 6, 2025):

refer to this - https://www.better-auth.com/docs/integrations/next#middleware

instead of just giving the documentation url, can you give more details? what is wrong with my code? As I explained, I already applied nextjs integration from the docs

<!-- gh-comment-id:2781302451 --> @sovetski commented on GitHub (Apr 6, 2025): > refer to this - https://www.better-auth.com/docs/integrations/next#middleware instead of just giving the documentation url, can you give more details? what is wrong with my code? As I explained, I already applied nextjs integration from the docs
Author
Owner

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

i just mentioned the docs incase you mistaken for the nextjs version and it does have a clear guide on that .. otherwise let me try it on my end and get back to you

<!-- gh-comment-id:2781321026 --> @Kinfe123 commented on GitHub (Apr 6, 2025): i just mentioned the docs incase you mistaken for the nextjs version and it does have a clear guide on that .. otherwise let me try it on my end and get back to you
Author
Owner

@sovetski commented on GitHub (Apr 6, 2025):

i just mentioned the docs incase you mistaken for the nextjs version and it does have a clear guide on that .. otherwise let me try it on my end and get back to you

I just tried without middleware, it works but when I put back middleware it does not work. I think it comes from "matcher" option, because on the docs it is always something like /dashboard but in my case to access to the application user have to login so instead of /dashboard it is / and maybe it stops api working correctly?

<!-- gh-comment-id:2781325956 --> @sovetski commented on GitHub (Apr 6, 2025): > i just mentioned the docs incase you mistaken for the nextjs version and it does have a clear guide on that .. otherwise let me try it on my end and get back to you I just tried without middleware, it works but when I put back middleware it does not work. I think it comes from "matcher" option, because on the docs it is always something like `/dashboard` but in my case to access to the application user have to login so instead of `/dashboard` it is `/` and maybe it stops api working correctly?
Author
Owner

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

i mean have you make sure you have followed the nextjs docs on migrating to support nodejs middleware as a runtime

<!-- gh-comment-id:2781330432 --> @Kinfe123 commented on GitHub (Apr 6, 2025): i mean have you make sure you have followed the nextjs docs on migrating to support nodejs middleware as a runtime
Author
Owner

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

plus to avoid any unnecessary blocks and database call, i recommend you using getSessionCookie


import { NextRequest, NextResponse } from "next/server";
import { getSessionCookie } from "better-auth/cookies";
export async function middleware(request: NextRequest) {
  const sessionCookie = getSessionCookie(request);
  const { pathname } = request.nextUrl;
  if (sessionCookie && ["/login", "/signup"].includes(pathname)) {
    return NextResponse.redirect(new URL("/dashboard", request.url));
  }
  if (!sessionCookie && pathname.startsWith("/dashboard")) {
    return NextResponse.redirect(new URL("/login", request.url));
  }
  return NextResponse.next();
}

export const config = {
  matcher: ["/dashboard", "/login", "/signup"],
};
<!-- gh-comment-id:2781331037 --> @Kinfe123 commented on GitHub (Apr 6, 2025): plus to avoid any unnecessary blocks and database call, i recommend you using `getSessionCookie` ```ts import { NextRequest, NextResponse } from "next/server"; import { getSessionCookie } from "better-auth/cookies"; export async function middleware(request: NextRequest) { const sessionCookie = getSessionCookie(request); const { pathname } = request.nextUrl; if (sessionCookie && ["/login", "/signup"].includes(pathname)) { return NextResponse.redirect(new URL("/dashboard", request.url)); } if (!sessionCookie && pathname.startsWith("/dashboard")) { return NextResponse.redirect(new URL("/login", request.url)); } return NextResponse.next(); } export const config = { matcher: ["/dashboard", "/login", "/signup"], }; ```
Author
Owner

@sovetski commented on GitHub (Apr 6, 2025):

Thank you so much @Kinfe123

It works better with getSessionCookie, the nodejs middleware is not ready to use I think, I applied everything from NextJS documentation but did not work, I will keep this usage for the moment

<!-- gh-comment-id:2781335882 --> @sovetski commented on GitHub (Apr 6, 2025): Thank you so much @Kinfe123 It works better with `getSessionCookie`, the nodejs middleware is not ready to use I think, I applied everything from NextJS documentation but did not work, I will keep this usage for the moment
Author
Owner

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

yeah you have to upgrade it to canary version and make sure to put experimental flag on next config but since there might be a bit of breaking change, it is better to stick with the the latest versions

<!-- gh-comment-id:2781337619 --> @Kinfe123 commented on GitHub (Apr 6, 2025): yeah you have to upgrade it to canary version and make sure to put experimental flag on next config but since there might be a bit of breaking change, it is better to stick with the the latest versions
Author
Owner

@iamtekeste commented on GitHub (Apr 27, 2025):

just incase it helps someone else in the future, i was seeing the same error because my aws rds db(which had better-auth tables) was in a different vpc than my lambda, which was in the default aws vpc. Putting them in the same vpc solved this issue for me.

<!-- gh-comment-id:2832911601 --> @iamtekeste commented on GitHub (Apr 27, 2025): just incase it helps someone else in the future, i was seeing the same error because my aws rds db(which had better-auth tables) was in a different vpc than my lambda, which was in the default aws vpc. Putting them in the same vpc solved this issue for me.
Author
Owner

@0xCodeMaieutics commented on GitHub (Jun 7, 2025):

Anyone getting issue with Prisma using better-auth SDK, just use default fetch API without specifying the runtime to Nodejs.

import { Session } from "better-auth";
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

export default async function middleware(req: NextRequest) {
  const res = await fetch(`${req.nextUrl.origin}/api/auth/get-session`, {
    method: "GET",
    headers: {
      cookie: req.headers.get("cookie") || "",
    },
  });

  if (!res.ok) {
    throw new Error("Failed to fetch session");
  }

  const session: Session = await res.json();

  if (!session) return NextResponse.redirect(new URL("/login", req.url));

  return NextResponse.next();
}

export const config = {
  matcher: "/",
};

<!-- gh-comment-id:2952189471 --> @0xCodeMaieutics commented on GitHub (Jun 7, 2025): Anyone getting issue with Prisma using better-auth SDK, just use default fetch API without specifying the runtime to Nodejs. ```ts import { Session } from "better-auth"; import { NextResponse } from "next/server"; import type { NextRequest } from "next/server"; export default async function middleware(req: NextRequest) { const res = await fetch(`${req.nextUrl.origin}/api/auth/get-session`, { method: "GET", headers: { cookie: req.headers.get("cookie") || "", }, }); if (!res.ok) { throw new Error("Failed to fetch session"); } const session: Session = await res.json(); if (!session) return NextResponse.redirect(new URL("/login", req.url)); return NextResponse.next(); } export const config = { matcher: "/", }; ```
Author
Owner

@w3sync commented on GitHub (Aug 29, 2025):

I'm facing the same issue. In my case, the real problem was the table name user. I think user is a reserved keyword in many PostgreSQL databases, so I renamed it to users, and it worked.

In Schema file

export const user = pgTable("user", {    <------------------------------- table name: 'user'  
	id: text("id").primaryKey(),
	name: text("name").notNull(),
	...

export const user = pgTable("users", { <---------------------------------- table name: 'users' ✔️  
	id: text("id").primaryKey(),
	name: text("name").notNull(),
	...
<!-- gh-comment-id:3237753505 --> @w3sync commented on GitHub (Aug 29, 2025): I'm facing the same issue. In my case, the real problem was the table name user. I think user is a reserved keyword in many PostgreSQL databases, so I renamed it to users, and it worked. In Schema file ```ts export const user = pgTable("user", { <------------------------------- table name: 'user' ❌ id: text("id").primaryKey(), name: text("name").notNull(), ... export const user = pgTable("users", { <---------------------------------- table name: 'users' ✔️ id: text("id").primaryKey(), name: text("name").notNull(), ... ```
Author
Owner

@jacksontriffon commented on GitHub (Nov 24, 2025):

In case anyone else finds this, removing middleware should fix this issue

It works better with getSessionCookie, the nodejs middleware is not ready to use I think, I applied everything from NextJS documentation but did not work, I will keep this usage for the moment

<!-- gh-comment-id:3573203979 --> @jacksontriffon commented on GitHub (Nov 24, 2025): In case anyone else finds this, removing middleware should fix this issue > It works better with `getSessionCookie`, the nodejs middleware is not ready to use I think, I applied everything from NextJS documentation but did not work, I will keep this usage for the moment
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#9066