Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Runtime Error: Authentication crash when using PrismaAdapter (mongodb) - TypeError: Cannot read properties of undefined (reading 'exec') #12731

Open
th3f0r3ign3r opened this issue Mar 4, 2025 · 24 comments · May be fixed by #12755
Labels
bug Something isn't working triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime.

Comments

@th3f0r3ign3r
Copy link

Environment

System:
    OS: macOS 15.3.1
    CPU: (8) arm64 Apple M2
    Memory: 1.02 GB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 22.14.0 - ~/.nvm/versions/node/v22.14.0/bin/node
    npm: 11.1.0 - ~/.nvm/versions/node/v22.14.0/bin/npm
    Watchman: 2024.12.02.00 - /opt/homebrew/bin/watchman
  Browsers:
    Safari: 18.3
  npmPackages:
    @auth/prisma-adapter: ^2.8.0 => 2.8.0
    next: 15.2.0 => 15.2.0
    next-auth: ^5.0.0-beta.25 => 5.0.0-beta.25
    react: ^19.0.0 => 19.0.0

Reproduction URL

https://github.com/th3f0r3ign3r/authjs-issue.git

Describe the issue

I have setting up Auth.js with Github Oauth and I decided to add PrismaAdapter with (mongodb) to save user account information. Without adding the adapter everything working great. But when I added the Adapter to @/auth it crash

Image

Image

CleanShot.2025-03-04.at.19.35.44.mp4

How to reproduce

  1. Clone the project
  2. Create a Github App (CLIENT_ID & CLIENT_SECRET)
  3. Create a MongoBD account and get a connection string
  4. Add them to the .env.local & run npx prisma generate
  5. Go to src/auth/index.tscomment the adapters line
  6. Launch the project clear && npm run dev don’t forget to run npm i
  7. Click on the Signin with GitHub
  8. After being logged signOut
  9. Uncomment the adapter line
  10. Refresh your browser

If you follow all these steps normally you will have the same error

Expected behavior

Normally they should not have any error. Instead I am doing something wrong but I follow the guide line per line. 😩😩😩

@th3f0r3ign3r th3f0r3ign3r added bug Something isn't working triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime. labels Mar 4, 2025
@activemonkeys
Copy link

The @auth/prisma-adapter version ^2.8.0 is not compatible with next-auth version ^5.0.0-beta.25. To resolve this issue, revert to @auth/prisma-adapter version 2.7.2 and install it without the ^ symbol to prevent unintended updates.

@th3f0r3ign3r
Copy link
Author

The @auth/prisma-adapter version ^2.8.0 is not compatible with next-auth version ^5.0.0-beta.25. To resolve this issue, revert to @auth/prisma-adapter version 2.7.2 and install it without the ^ symbol to prevent unintended updates.

Thanks I will try it

@poksme
Copy link

poksme commented Mar 5, 2025

I am having the same error with a similar stack :

  npmPackages:
    @auth/prisma-adapter: ^2.8.0 => 2.8.0
    next: ^15.2.1 => 15.2.1
    next-auth: 5.0.0-beta.25 => 5.0.0-beta.25
    react: ^19.0.0 => 19.0.0

using PostgreSQL / Neon (I don't think the actual DB is related to this issue).

Thankfully, I got this error at build time, this was a bit more explicit than your logs :

> next build --experimental-build-mode compile
Failed to compile.

./src/lib/auth.ts
Dynamic Code Evaluation (e. g. 'eval', 'new Function', 'WebAssembly.compile') not allowed in Edge Runtime 
Learn More: https://nextjs.org/docs/messages/edge-dynamic-code-evaluation

The error was caused by importing '@auth/prisma-adapter/index.js' in './src/lib/auth.ts'.

Import trace for requested module:
  ./src/lib/auth.ts
  ./src/middleware.ts

For reference, the source of the related files
lib/auth.ts

// Following this guide
// https://authjs.dev/getting-started/adapters/prisma
import { PrismaAdapter } from "@auth/prisma-adapter";
import type { PrismaNeon } from "@prisma/adapter-neon";
import type { PrismaClient } from "@prisma/client";
import type { NextAuthConfig } from "next-auth";
import NextAuth from "next-auth";
import GitHub from "next-auth/providers/github";

import prisma from "@/lib/prisma";

export const { handlers, auth, signIn, signOut } = NextAuth({
  providers: [GitHub],
  callbacks: {
    session({ session, user }) {
      // As seen on https://authjs.dev/guides/role-based-access-control
      if (user?.id) session.user.id = user.id;
      if (user?.role) session.user.role = user.role;
      return session;
    },
  },
  adapter: PrismaAdapter(
    prisma as PrismaClient<{ adapter: PrismaNeon }>,
  ) as NextAuthConfig["adapter"], // Need to type cast as we extend the payload of session
});

middleware.ts

// Only one middleware, used to refresh the token
export { auth as middleware } from "@/lib/auth";

@activemonkeys @th3f0r3ign3r not that it fixes the current problem, in my case I was able to lock version ~2.7.4 without issue.

@th3f0r3ign3r
Copy link
Author

The @auth/prisma-adapter version ^2.8.0 is not compatible with next-auth version ^5.0.0-beta.25. To resolve this issue, revert to @auth/prisma-adapter version 2.7.2 and install it without the ^ symbol to prevent unintended updates.

I almost forgot my problem is solved
Thanks @activemonkeys

@th3f0r3ign3r
Copy link
Author

I am having the same error with a similar stack :

  npmPackages:
    @auth/prisma-adapter: ^2.8.0 => 2.8.0
    next: ^15.2.1 => 15.2.1
    next-auth: 5.0.0-beta.25 => 5.0.0-beta.25
    react: ^19.0.0 => 19.0.0

using PostgreSQL / Neon (I don't think the actual DB is related to this issue).

Thankfully, I got this error at build time, this was a bit more explicit than your logs :

> next build --experimental-build-mode compile
Failed to compile.

./src/lib/auth.ts
Dynamic Code Evaluation (e. g. 'eval', 'new Function', 'WebAssembly.compile') not allowed in Edge Runtime 
Learn More: https://nextjs.org/docs/messages/edge-dynamic-code-evaluation

The error was caused by importing '@auth/prisma-adapter/index.js' in './src/lib/auth.ts'.

Import trace for requested module:
  ./src/lib/auth.ts
  ./src/middleware.ts

For reference, the source of the related files
lib/auth.ts

// Following this guide
// https://authjs.dev/getting-started/adapters/prisma
import { PrismaAdapter } from "@auth/prisma-adapter";
import type { PrismaNeon } from "@prisma/adapter-neon";
import type { PrismaClient } from "@prisma/client";
import type { NextAuthConfig } from "next-auth";
import NextAuth from "next-auth";
import GitHub from "next-auth/providers/github";

import prisma from "@/lib/prisma";

export const { handlers, auth, signIn, signOut } = NextAuth({
  providers: [GitHub],
  callbacks: {
    session({ session, user }) {
      // As seen on https://authjs.dev/guides/role-based-access-control
      if (user?.id) session.user.id = user.id;
      if (user?.role) session.user.role = user.role;
      return session;
    },
  },
  adapter: PrismaAdapter(
    prisma as PrismaClient<{ adapter: PrismaNeon }>,
  ) as NextAuthConfig["adapter"], // Need to type cast as we extend the payload of session
});

middleware.ts

// Only one middleware, used to refresh the token
export { auth as middleware } from "@/lib/auth";

@activemonkeys @th3f0r3ign3r not that it fixes the current problem, in my case I was able to lock version ~2.7.4 without issue.

Great 👍 I will try 2.7.4 to see if it will still work.

@abrunner94
Copy link

Shit like this is exactly why I hate but also love NextAuth, Auth.js, whatever we call it today.

@poksme
Copy link

poksme commented Mar 6, 2025

@th3f0r3ign3r I am not sure why you consider this issue solved, I think prisma-adapter ^2.8.0 is supposed to work with ^5.0.0-beta.25. @activemonkeys and I were just providing a stopgap solution until the issue is fixed.

@th3f0r3ign3r th3f0r3ign3r reopened this Mar 6, 2025
@th3f0r3ign3r
Copy link
Author

@th3f0r3ign3r I am not sure why you consider this issue solved, I think prisma-adapter ^2.8.0 is supposed to work with ^5.0.0-beta.25. @activemonkeys and I were just providing a stopgap solution until the issue is fixed.

my bad though

@bunnyxt
Copy link

bunnyxt commented Mar 8, 2025

Same here, for PrismaAdapter with Postgres

@QC2168

This comment has been minimized.

@i-naeem
Copy link

i-naeem commented Mar 12, 2025

The @auth/prisma-adapter version ^2.8.0 is not compatible with next-auth version ^5.0.0-beta.25. To resolve this issue, revert to @auth/prisma-adapter version 2.7.2 and install it without the ^ symbol to prevent unintended updates.

I almost forgot my problem is solved Thanks @activemonkeys

Thanks for pointing this out! I was facing the same issue, and downgrading @auth/prisma-adapter to 2.7.2 worked for me as well.

@CollinsKippy
Copy link

The @auth/prisma-adapter version ^2.8.0 is not compatible with next-auth version ^5.0.0-beta.25. To resolve this issue, revert to @auth/prisma-adapter version 2.7.2 and install it without the ^ symbol to prevent unintended updates.

Great! After wrestling with this issue the whole weekend in a newly created NextJS project, this was the solution. Initially thought it was a NextJS v15 problem.

@Lucas070713
Copy link

Changing to 2.7.4 eliminates the error but introduces a new error.

Image

@i-naeem
Copy link

i-naeem commented Mar 20, 2025

Changing to 2.7.4 eliminates the error but introduces a new error.

Image

Are you using middleware in next.js?

@Lucas070713
Copy link

Changing to 2.7.4 eliminates the error but introduces a new error.
Image

Are you using middleware in next.js?

Changing to 2.7.4 eliminates the error but introduces a new error.
Image

Are you using middleware in next.js?

yes
middleware.ts

export { auth as middleware } from "@/auth";

export const config = {
  matcher: [
    /*
     * Match all request paths except for the ones starting with:
     * - _next/static (static files)
     * - _next/image (image optimization files)
     * - favicon.ico (favicon file)
     * Feel free to modify this pattern to include more paths.
     */
    {
      source:
        "/((?!api|webhook|_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|mp3)$).*)",
      missing: [
        { type: "header", key: "next-router-prefetch" },
        { type: "header", key: "purpose", value: "prefetch" },
      ],
    },
  ],
};

auth.ts

import { PrismaAdapter } from "@auth/prisma-adapter";
import NextAuth from "next-auth";
import { type Adapter } from "next-auth/adapters";
import { Provider } from "next-auth/providers";
import Discord from "next-auth/providers/discord";
import { prisma } from "./lib/prisma";

const providers: Provider[] = [Discord];

export const { handlers, signIn, signOut, auth } = NextAuth({
  adapter: PrismaAdapter(prisma) as Adapter,
  providers,
  callbacks: {
    authorized({ request: { nextUrl }, auth }) {
      const isLoggedIn = !!auth?.user;

      const { pathname } = nextUrl;

      const role = auth?.user.role || "GUEST";

      const publicPaths = ["/auth/signin", "/auth/signout"];

      if (!isLoggedIn || role === "GUEST") {
        if (!publicPaths.includes(pathname)) {
          return Response.redirect(new URL("/auth/signin", nextUrl));
        }
      }

      return !!auth;
    },
    jwt({ token, user }) {
      if (user) {
        token.id = user.id as string;
        token.role = user.role as string;
      }
      return token;
    },
    session({ session, token }) {
      session.user.id = token.id;
      session.user.role = token.role;
      return session;
    },
  },
  pages: {
    signIn: "/auth/signin",
    signOut: "/auth/signout",
  },
});

export const providerMap = providers
  .map((provider) => {
    if (typeof provider === "function") {
      const providerData = provider();
      return { id: providerData.id, name: providerData.name };
    } else {
      return { id: provider.id, name: provider.name };
    }
  })
  .filter((provider) => provider.id !== "credentials");

package.json

{
  "name": "v2",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev --port 17600",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "@auth/prisma-adapter": "^2.7.0",
    "@icons-pack/react-simple-icons": "^12.3.0",
    "@prisma/client": "^6.5.0",
    "@prisma/extension-accelerate": "^1.3.0",
    "@radix-ui/react-slot": "^1.1.2",
    "class-variance-authority": "^0.7.1",
    "clsx": "^2.1.1",
    "lucide-react": "^0.483.0",
    "next": "15.2.3",
    "next-auth": "^5.0.0-beta.25",
    "next-themes": "^0.4.6",
    "react": "^19.0.0",
    "react-dom": "^19.0.0",
    "sonner": "^2.0.1",
    "tailwind-merge": "^3.0.2",
    "tw-animate-css": "^1.2.4",
    "zod": "^3.24.2"
  },
  "devDependencies": {
    "@eslint/eslintrc": "^3",
    "@tailwindcss/postcss": "^4",
    "@types/node": "^20",
    "@types/react": "^19",
    "@types/react-dom": "^19",
    "eslint": "^9",
    "eslint-config-next": "15.2.3",
    "prisma": "^6.5.0",
    "tailwindcss": "^4",
    "typescript": "^5"
  }
}

@i-naeem
Copy link

i-naeem commented Mar 20, 2025

@Lucas070713
Hey, so I was also having same issue I think that auth middleware does not run in the edge environment when using Prisma adapter.
Check out this link https://authjs.dev/guides/edge-compatibility#middleware. I'd also suggest you check this page for more details on compatible drivers and their respective adapters. https://www.prisma.io/docs/orm/prisma-client/deployment/edge/deploy-to-vercel#using-an-edge-compatible-driver

I end up creating my own middleware to handle the authentication instead of relying on the one provided by auth.js and that work for me if you want, I can share that with you as well.

@Lucas070713
Copy link

@i-naeem
schema.prisma

generator client {
  provider = "prisma-client-js"
  previewFeatures = ["driverAdapters"]
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
  directUrl = env("DIRECT_URL")
}

What kind of middleware should be implemented that does not depend on auth.js?

@i-naeem
Copy link

i-naeem commented Mar 20, 2025

This is the one I am referring to. try to remove the middleware for a moment and see if your app works correctly.

export { auth as middleware } from "@/auth";

export const config = {
  matcher: [
    /*
     * Match all request paths except for the ones starting with:
     * - _next/static (static files)
     * - _next/image (image optimization files)
     * - favicon.ico (favicon file)
     * Feel free to modify this pattern to include more paths.
     */
    {
      source:
        "/((?!api|webhook|_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|mp3)$).*)",
      missing: [
        { type: "header", key: "next-router-prefetch" },
        { type: "header", key: "purpose", value: "prefetch" },
      ],
    },
  ],
};

@Lucas070713
Copy link

@i-naeem
It works when middleware is turned off.
However, RBAC no longer works!

callbacks: {
    authorized({ request: { nextUrl }, auth }) {
      const isLoggedIn = !!auth?.user;

      const { pathname } = nextUrl;

      const role = auth?.user.role || "GUEST";

      const publicPaths = ["/auth/signin", "/auth/signout"];

      console.log(nextUrl, auth);

      if (!isLoggedIn || role === "GUEST") {
        if (!publicPaths.includes(pathname)) {
          return Response.redirect(new URL("/auth/signin", nextUrl));
        }
      }

      return !!auth;
    },
    jwt({ token, user }) {
      if (user) {
        token.id = user.id as string;
        token.role = user.role as string;
      }
      return token;
    },
    session({ session, token }) {
      session.user.id = token.id;
      session.user.role = token.role;
      return session;
    },
  },

@i-naeem
Copy link

i-naeem commented Mar 20, 2025

You will have to check out these two links if you want to make this middleware from auth.js to work
https://www.prisma.io/docs/orm/prisma-client/deployment/edge/deploy-to-vercel#using-an-edge-compatible-driver
https://authjs.dev/guides/edge-compatibility#middleware

Otherwise here is the middleware I wrote which worked for me. You can modify this one to add RBAC mechanism as well.

import { NextResponse } from 'next/server';
import { getToken } from 'next-auth/jwt';

const protectedRoutes = ['/dashboard'];
const authRoutes = ['/login', '/register']; // Routes to restrict for logged-in users

export async function middleware(req) {
  const sessionToken = req.cookies.get('authjs.session-token')?.value;
  const currentPath = req.nextUrl.pathname;

  // Check if user is authenticated
  let isAuthenticated = false;
  if (sessionToken) {
    try {
      const decodedToken = await getToken({ req, secret: process.env.AUTH_SECRET });
      isAuthenticated = !!decodedToken;
    } catch (error) {
      console.error('Failed to decode session token:', error);
    }
  }

  // Redirect unauthorized users trying to access protected routes
  if (protectedRoutes.some(route => currentPath.startsWith(route))) {
    if (!isAuthenticated) {
      return NextResponse.redirect(new URL('/login', req.url));
    }
  }

  // Redirect logged-in users away from login or register pages
  if (isAuthenticated && authRoutes.includes(currentPath)) {
    return NextResponse.redirect(new URL('/dashboard', req.url)); // Redirect to dashboard or another page
  }

  return NextResponse.next();
}

export const config = {
  matcher: ['/dashboard/:path*', '/login', '/register'], // Apply middleware to relevant routes
};

@Lucas070713
Copy link

@i-naeem
The sessionToken is obtained and the decodedToken is null.
We have confirmed that the browser cookie has authjs.session-token.

middleware.ts

import { getToken } from "next-auth/jwt";
import { NextRequest, NextResponse } from "next/server";

const publicPaths = ["/auth/signin", "/auth/signout"];
const authPaths = ["/auth/signin"];

export async function middleware(req: NextRequest) {
  const sessionToken = req.cookies.get("authjs.session-token")?.value;
  const currentPath = req.nextUrl.pathname;
  console.log(sessionToken);

  let isAuthenticated = false;
  if (sessionToken) {
    try {
      const decodedToken = await getToken({
        req,
        secret: process.env.AUTH_SECRET,
      });
      console.log(decodedToken);
      isAuthenticated = !!decodedToken;
    } catch (error) {
      console.error("Failed to decode session token:", error);
    }
  }

  console.log(isAuthenticated);

  if (!publicPaths.includes(currentPath)) {
    if (!isAuthenticated) {
      return NextResponse.redirect(new URL("/auth/signin", req.url));
    }
  }

  if (isAuthenticated && authPaths.includes(currentPath)) {
    return NextResponse.redirect(new URL("/", req.url));
  }

  return NextResponse.next();
}

export const config = {
  matcher: [
    /*
     * Match all request paths except for the ones starting with:
     * - _next/static (static files)
     * - _next/image (image optimization files)
     * - favicon.ico (favicon file)
     * Feel free to modify this pattern to include more paths.
     */
    {
      source:
        "/((?!api|webhook|_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|mp3)$).*)",
      missing: [
        { type: "header", key: "next-router-prefetch" },
        { type: "header", key: "purpose", value: "prefetch" },
      ],
    },
  ],
};

@Lucas070713
Copy link

Resolved.
I was able to implement this by setting the session strategy to jwt.

@i-naeem
Copy link

i-naeem commented Mar 20, 2025

Resolved. I was able to implement this by setting the session strategy to jwt.

good to hear and I am happy that I could help a little.

@m-mohammad-d
Copy link

The @auth/prisma-adapter version ^2.8.0 is not compatible with next-auth version ^5.0.0-beta.25. To resolve this issue, revert to @auth/prisma-adapter version 2.7.2 and install it without the ^ symbol to prevent unintended updates.

Thank you so much for the help! I had the same issue, and following your suggestion to revert to @auth/prisma-adapter version 2.7.2 without the ^ fixed the problem. It worked perfectly! I really appreciate your guidance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants