(on middleware) [Better Auth]: INTERNAL_SERVER_ERROR Error: Failed query

2025-08-10T13:39:59.581Z ERROR [Better Auth]: INTERNAL_SERVER_ERROR Error: Failed query: select "id", "expires_at", "token", "created_at", "updated_at", "ip_address", "user_agent", "user_id", "impersonated_by" from "session" where "session"."token" = $1
params: 7lIiWUkRjrVmOh4UJ0rZgjrvITaKu3ve


This occurs in my middleware.ts:
import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/lib/auth";

export async function middleware(request: NextRequest) {
  const { pathname } = request.nextUrl;

  // Skip setup check for setup page and API routes
  if (pathname.startsWith("/setup") || pathname.startsWith("/api/setup")) {
    return NextResponse.next();
  }

  // Check if setup is needed (except for setup-related routes)
  try {
    const setupResponse = await fetch(new URL("/api/setup/check", request.url));
    if (setupResponse.ok) {
      const setupData = await setupResponse.json();
      if (setupData.needsSetup) {
        return NextResponse.redirect(new URL("/setup", request.url));
      }
    }
  } catch (error) {
    console.error("Setup check error:", error);
  }

  // Only protect admin routes
  if (pathname.startsWith("/admin")) {
    try {
      const session = await auth.api.getSession({
        headers: request.headers,
      });

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

      // Check if user has admin/staff role
      if (
        !session.user.role ||
        !["admin", "staff"].includes(session.user.role)
      ) {
        return NextResponse.redirect(new URL("/", request.url));
      }
    } catch (error) {
      console.error("Middleware auth error:", error);
      return NextResponse.redirect(new URL("/login", request.url));
    }
  }

  return NextResponse.next();
}

export const config = {
  matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"],
};


My auth.ts looks like this:

import { betterAuth } from "better-auth";
import { admin, apiKey } from "better-auth/plugins";
import { nextCookies } from "better-auth/next-js";
import { createAccessControl } from "better-auth/plugins/access";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { db } from "./db";
import { account, apikey, session, user, verification } from "./db/schema";

import { ac, userRole, adminRole, staffRole } from "./access-control";

export const auth = betterAuth({
  database: drizzleAdapter(db, {
    provider: "pg",
    schema: {
      user,
      account,
      session,
      verification,
      apikey,
    },
  }),
  emailAndPassword: {
    enabled: true,
    requireEmailVerification: false,
  },
  session: {
    expiresIn: 60 * 60 * 24 * 7, // 7 days
    updateAge: 60 * 60 * 24, // 1 day
  },
  plugins: [
    admin({
      ac,
      roles: {
        user: userRole,
        staff: staffRole,
        admin: adminRole,
      },
    }),
    apiKey(),
    nextCookies(), // Must be the last plugin in the array
  ],
});

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


My auth-client.ts looks like this:
import { createAuthClient } from "better-auth/react";
import { inferAdditionalFields, adminClient } from "better-auth/client/plugins";
import type { auth } from "./auth";
import { ac, userRole, staffRole, adminRole } from "./access-control";

export const authClient = createAuthClient({
  baseURL: process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000",
  plugins: [
    inferAdditionalFields<typeof auth>(),
    adminClient({
      ac,
      roles: {
        user: userRole,
        staff: staffRole,
        admin: adminRole,
      },
    }),
  ],
});

export const { useSession, signIn, signOut, signUp } = authClient;
Was this page helpful?