nextauthjs / next-auth

Authentication for the Web.
https://authjs.dev
ISC License
22.87k stars 3.08k forks source link

Auth v5 - Prisma Adapter with Google Provider on Runtime Edge - [TypeError]: immutable #9300

Closed riccardolinares closed 4 weeks ago

riccardolinares commented 6 months ago

Adapter type

@auth/prisma-adapter

Environment

System: OS: macOS 14.1.1 CPU: (8) x64 Intel(R) Core(TM) i5-8259U CPU @ 2.30GHz Memory: 44.29 MB / 8.00 GB Shell: 3.2.57 - /bin/bash Binaries: Node: 20.10.0 - /usr/local/bin/node npm: 10.2.4 - /usr/local/bin/npm Browsers: Chrome: 119.0.6045.199 Safari: 17.1 npmPackages: @auth/prisma-adapter: ^1.0.8 => 1.0.8 next: ^14.0.3 => 14.0.3 next-auth: ^5.0.0-beta.4 => 5.0.0-beta.4 react: ^18 => 18.2.0

Reproduction URL

https://github.com/riccardolinares/next-auth-v5

Describe the issue

I am currently working on a project that utilizes the Prisma adapter in conjunction with Prisma Accelerate. However, I am encountering a persistent and somewhat random error related to the Prisma Adapter, then a Session error and at the end I get an Error [TypeError]: immutable when I try to login again using the google provider.

I am not sure if it's related mainly to the adapter itself or to the Google Provider. It is driving me crazy!

The issue mainly arises when a user is logged in for an unspecified duration. Unfortunately, the error's sporadic nature makes it difficult to reproduce reliably, complicating the troubleshooting process.

Key points to note:

Attempts to Resolve:

I have tried to monitor the application to pinpoint the cause but due to the randomness of the error, this approach has not yielded any significant insights. I have also checked for any potential updates or patches for Prisma and Next.js that might address this issue but have not found any relevant updates.

Additional Information:

There are no clear patterns or specific user actions that seem to trigger this error. The application logs do not provide detailed information that could help in isolating the problem. I am looking for any guidance or suggestions on how to approach this issue, especially from others who might have encountered similar problems with Prisma Adapter and Prisma Accelerate on Next.js Runtime Edge.

Here is the log of the error:

[auth][error] AdapterError: Read more at https://errors.authjs.dev#adaptererror
[auth][cause]: PrismaClientUnknownRequestError: 
Invalid `prisma.session.findUnique()` invocation:

Error occurred during query execution:
ConnectorError(ConnectorError { user_facing_error: None, kind: QueryError(PostgresError { code: "26000", message: "prepared statement \"s489\" does not exist", severity: "ERROR", detail: None, column: None, hint: None }), transient: false })
    at Ei.handleRequestError (/Users/ac/RiccardoProjects/secondsoul/node_modules/@prisma/client/runtime/edge.js:84:7381)
    at Ei.handleAndLogRequestError (/Users/ac/RiccardoProjects/secondsoul/node_modules/@prisma/client/runtime/edge.js:84:6595)
    at Ei.request (/Users/ac/RiccardoProjects/secondsoul/node_modules/@prisma/client/runtime/edge.js:84:6293)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async u (/Users/ac/RiccardoProjects/secondsoul/node_modules/@prisma/client/runtime/edge.js:89:10383)
    at async getSessionAndUser (webpack-internal:///(rsc)/./node_modules/@auth/prisma-adapter/index.js:250:36)
    at async acc.<computed> (webpack-internal:///(rsc)/./node_modules/next-auth/node_modules/@auth/core/lib/init.js:169:24)
    at async Module.session (webpack-internal:///(rsc)/./node_modules/next-auth/node_modules/@auth/core/lib/actions/session.js:84:30)
    at async AuthInternal (webpack-internal:///(rsc)/./node_modules/next-auth/node_modules/@auth/core/lib/index.js:50:24)
    at async Auth (webpack-internal:///(rsc)/./node_modules/next-auth/node_modules/@auth/core/index.js:123:29)
    at async ChatPage (webpack-internal:///(rsc)/./src/app/(private)/chat/[id]/page.tsx:43:21)
[auth][details]: {}
[auth][error] SessionTokenError: Read more at https://errors.authjs.dev#sessiontokenerror
[auth][cause]: PrismaClientUnknownRequestError: 
Invalid `prisma.session.findUnique()` invocation:

Error occurred during query execution:
ConnectorError(ConnectorError { user_facing_error: None, kind: QueryError(PostgresError { code: "26000", message: "prepared statement \"s489\" does not exist", severity: "ERROR", detail: None, column: None, hint: None }), transient: false })
    at Ei.handleRequestError (/Users/ac/RiccardoProjects/secondsoul/node_modules/@prisma/client/runtime/edge.js:84:7381)
    at Ei.handleAndLogRequestError (/Users/ac/RiccardoProjects/secondsoul/node_modules/@prisma/client/runtime/edge.js:84:6595)
    at Ei.request (/Users/ac/RiccardoProjects/secondsoul/node_modules/@prisma/client/runtime/edge.js:84:6293)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async u (/Users/ac/RiccardoProjects/secondsoul/node_modules/@prisma/client/runtime/edge.js:89:10383)
    at async getSessionAndUser (webpack-internal:///(rsc)/./node_modules/@auth/prisma-adapter/index.js:250:36)
    at async acc.<computed> (webpack-internal:///(rsc)/./node_modules/next-auth/node_modules/@auth/core/lib/init.js:169:24)
    at async Module.session (webpack-internal:///(rsc)/./node_modules/next-auth/node_modules/@auth/core/lib/actions/session.js:84:30)
    at async AuthInternal (webpack-internal:///(rsc)/./node_modules/next-auth/node_modules/@auth/core/lib/index.js:50:24)
    at async Auth (webpack-internal:///(rsc)/./node_modules/next-auth/node_modules/@auth/core/index.js:123:29)
    at async ChatPage (webpack-internal:///(rsc)/./src/app/(private)/chat/[id]/page.tsx:43:21)
[auth][details]: {}

...After multiple errors like the previous one, if I try to login again, then I get:

error { error: 'invalid_grant', error_description: 'Bad Request' }
[auth][error] CallbackRouteError: Read more at https://errors.authjs.dev#callbackrouteerror
[auth][cause]: Error: TODO: Handle OIDC response body error
    at handleOAuth (webpack-internal:///(rsc)/./node_modules/next-auth/node_modules/@auth/core/lib/actions/callback/oauth/callback.js:80:19)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Module.callback (webpack-internal:///(rsc)/./node_modules/next-auth/node_modules/@auth/core/lib/actions/callback/index.js:33:41)
    at async AuthInternal (webpack-internal:///(rsc)/./node_modules/next-auth/node_modules/@auth/core/lib/index.js:42:24)
    at async Auth (webpack-internal:///(rsc)/./node_modules/next-auth/node_modules/@auth/core/index.js:123:29)
    at async eval (webpack-internal:///(rsc)/./node_modules/next/dist/esm/server/future/route-modules/app-route/module.js:215:37)
[auth][details]: {
  "provider": "google"
}
 ⨯ Error [TypeError]: immutable
    at _Headers.delete (file:///Users/ac/RiccardoProjects/secondsoul/node_modules/next/dist/compiled/edge-runtime/index.js:1:657096)
    at runWithTaggedErrors (file:///Users/ac/RiccardoProjects/secondsoul/node_modules/next/dist/server/web/sandbox/sandbox.js:106:43)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async DevServer.runEdgeFunction (file:///Users/ac/RiccardoProjects/secondsoul/node_modules/next/dist/server/next-server.js:1169:24)
    at async NextNodeServer.handleCatchallRenderRequest (file:///Users/ac/RiccardoProjects/secondsoul/node_modules/next/dist/server/next-server.js:242:37)
    at async DevServer.handleRequestImpl (file:///Users/ac/RiccardoProjects/secondsoul/node_modules/next/dist/server/base-server.js:798:17)

Thank you for your attention to this matter. Any assistance or insights into this issue would be greatly appreciated.

How to reproduce

Unfortunately, the error's sporadic nature makes it difficult to reproduce reliably, complicating the troubleshooting process.

Expected behavior

Keep the user logged in and don't give the error "immutable"

DarKS4ys commented 6 months ago

I have this issue too

riccardolinares commented 6 months ago

The problem is not related to Google Provider. I am trying with other provider and getting the same error. It seems to be related to the Edge Runtime

riccardolinares commented 6 months ago

Note: I am using prisma accelerate as database url and I have also a database direct url in my env.

harisrab commented 6 months ago

I'm facing the same error right now.

taylor-lindores-reeves commented 6 months ago

Are there any docs on which adapters are edge-compatible?

franfdezmorales commented 6 months ago

facing same issue with edge on 5.0.0-beta.4, on 5.0.0-beta.3 its working fine.

snilan commented 6 months ago

Was getting this error before, but now I'm getting the following error:

TypeError: "response" must be an instance of Response

Using drizzle, node 18, and pnpm. Tried npm and node 16/20 as well

taylor-lindores-reeves commented 6 months ago

Was getting this error before, but now I'm getting the following error:

TypeError: "response" must be an instance of Response

Using drizzle, node 18, and pnpm. Tried npm and node 16/20 as well

Post your code please

snilan commented 6 months ago

Was getting this error before, but now I'm getting the following error: TypeError: "response" must be an instance of Response Using drizzle, node 18, and pnpm. Tried npm and node 16/20 as well

Post your code please

Here's the repo: https://github.com/snilan/next-auth-drizzle

I've been using https://github.com/nextauthjs/next-auth-v5-example as a guide

Thanks

martinzlocha commented 5 months ago

facing same issue with edge on 5.0.0-beta.4, on 5.0.0-beta.3 its working fine.

I am experiencing this also with 5.0.0-beta.3 as long as I am running on Vercel edge.

gagandua078 commented 5 months ago

``Still getting this issue should it be reported to next-auth or any work around yet ?

Server Error TypeError: immutable

Just to add this is my auth.ts

`/ eslint-disable @typescript-eslint/no-explicit-any / import axios from 'axios'; import NextAuth from 'next-auth'; import GitHub from 'next-auth/providers/github';

import Google from 'next-auth/providers/google';

import { User } from 'next-auth'; export interface AuthenticatedUser extends User { accessToken?: string; refreshToken?: string; }

export const { handlers: { GET, POST }, auth, } = NextAuth({ providers: [ GitHub({ clientId: process.env.OAUTH_CLIENT_KEY as string, clientSecret: process.env.OAUTH_CLIENT_SECRET as string, }), Google({ clientId: process.env.GOOGLE_CLIENT_ID as string, clientSecret: process.env.GOOGLE_CLIENT_SECRET as string, }), ], callbacks: { async signIn({ user, account, profile, }: { user: AuthenticatedUser; // Use your interface here account: any; // Define account type accordingly profile: any; // Define profile type accordingly }) { if (account.provider === 'google' && profile.verified_email === true) { const { accessToken, idToken } = account;

    try {
      const response = await axios.post(
        'http://127.0.0.1:8080/api/social/auth/google/',
        {
          access_token: accessToken,
          id_token: idToken,
        },
      );
      const access_token = response.data;
      user.accessToken = access_token;
      return true;
    } catch (error) {
      console.log(error);
      return false;
    }
  }
  return false;
},
async jwt({ token, user, account }) {
  if (user) {
    const { accessToken } = account;
    // reform the `token` object from the access token we appended to the `user` object
    // token = {
    //   ...token,
    //   accessToken,
    //   refreshToken,
    // };

    account.accessToken = accessToken;
    token = { accessToken: account.accessToken };
  }
  return token;
},

}, }); ` Any suggestions anyone ?

MilanObrenovic commented 5 months ago

I'm getting the same error. Trying to login with my github and the error is

[auth][details]: {}
 ⨯ Error [TypeError]: immutable

more logs

[auth][details]: {}
[auth][error] AdapterError: Read more at https://errors.authjs.dev#adaptererror
[auth][cause]: Error: PrismaClient is unable to run in Vercel Edge Functions. As an alternative, try Accelerate: https://pris.ly/d/accelerate.
If this is unexpected, please open an issue: https://github.com/prisma/prisma/issues

Using 5.0.0-beta.4, not using DIRECT_URL

MilanObrenovic commented 5 months ago

facing same issue with edge on 5.0.0-beta.4, on 5.0.0-beta.3 its working fine.

beta.3 doesn't work either for me

MilanObrenovic commented 5 months ago

I fixed it: https://authjs.dev/reference/adapter/prisma#create-the-prisma-schema-from-scratch

Please check and verify that the Account model is exactly like that. The fields need to be snake_case while providerAccountId must be camelCase. They were all camelCase for me

Also why so many inconsistencies? All models use camelCase notation while only Account model uses snake_case notation, and not even fully but partially. This is so stupid. And it's even more stupid that this HAS TO be exactly like that, no flexibility for me to modify those fields, not even change their casing convention

clkefe commented 5 months ago

[EDIT]: My solution also doesn't work... I will still keep what I tried, however, my ultimate solution was to switch to Supabase Auth.

...

After spending hours, I found a solution that worked for me!!

First of all, let's discuss what might cause the issue Error [TypeError]: immutable. As my understanding, the reason is that while NextAuth v5 is fully Edge-compatible, some providers (e.g., Primsa) are not.

Luckily, there is a workaround for that. I will not explain each step here since it is a relatively long process. However, you can easily follow the two guides I will provide.

1) Split the auth configuration into multiple files: https://authjs.dev/guides/upgrade-to-v5#edge-compatibility 2) Setup Prisma Accelerate: https://www.prisma.io/docs/accelerate/getting-started

Important points I encountered:

I hope this helps!

LegendNihal commented 4 months ago

After spending hours, I found a solution that worked for me!!

First of all, let's discuss what might cause the issue Error [TypeError]: immutable. As my understanding, the reason is that while NextAuth v5 is fully Edge-compatible, some providers (e.g., Primsa) are not.

Luckily, there is a workaround for that. I will not explain each step here since it is a relatively long process. However, you can easily follow the two guides I will provide.

  1. Split the auth configuration into multiple files: https://authjs.dev/guides/upgrade-to-v5#edge-compatibility
  2. Setup Prisma Accelerate: https://www.prisma.io/docs/accelerate/getting-started

Important points I encountered:

  • After enabling Prisma Accelerate, you have to click the "Generate API Key" button and change your DATABASE_URL in your .env file with that new connection string.
  • You will import your Prisma Client from here import { PrismaClient } from "@prisma/client/edge";
  • You have to use the JWT session strategy.

I hope this helps!

After spending hours, I found a solution that worked for me!!

First of all, let's discuss what might cause the issue Error [TypeError]: immutable. As my understanding, the reason is that while NextAuth v5 is fully Edge-compatible, some providers (e.g., Primsa) are not.

Luckily, there is a workaround for that. I will not explain each step here since it is a relatively long process. However, you can easily follow the two guides I will provide.

  1. Split the auth configuration into multiple files: https://authjs.dev/guides/upgrade-to-v5#edge-compatibility
  2. Setup Prisma Accelerate: https://www.prisma.io/docs/accelerate/getting-started

Important points I encountered:

  • After enabling Prisma Accelerate, you have to click the "Generate API Key" button and change your DATABASE_URL in your .env file with that new connection string.
  • You will import your Prisma Client from here import { PrismaClient } from "@prisma/client/edge";
  • You have to use the JWT session strategy.

I hope this helps!

its not a solution brother. spliting authconfig to diff file makes middleware not edge runtime hence the prob isnt there. The Job of accelerate is to run it on edge runtime

clkefe commented 4 months ago

@LegendNihal Yes.. I realized that after I commented. I guess it only worked for a little while when I did those. Thank you for reminding me! I will edit my comment :)

ndom91 commented 4 months ago

Yeah unfortunately Prisma is not yet fully compatible with edge runtimes. If you want to use the Auth.js middleware, you can either force a JWT session (session: 'jwt') and skip the database part.

Or if you need the database, you can remove the middleware.ts file and skip the middleware functionality from Auth.js.

You can also follow along Prisma's issue for this topic here - https://github.com/prisma/prisma/issues/21394

Also see our note about this here.

Another alternative would be using Prisma's "Accelerate" platform which is compatible: https://www.prisma.io/data-platform/accelerate

clieee commented 4 months ago

Im using postgres via vercel and facing issues with middleware check even locally. Is that the way it is, or can I get it to work locally?

Right now I've skipped middleware check if the user is authorized so my question is, if Im not using the middleware, how are you then checking if the user is logged in for all my routes server side?

ndom91 commented 4 months ago

So Prisma's just shipped an update that handles htis a bit more gracefully. Can you give @prisma/client@5.9.1 a try?

Right now I've skipped middleware check if the user is authorized so my question is, if Im not using the middleware, how are you then checking if the user is logged in for all my routes server side?

Not unless your doing a check in each route. There's no magic here :sweat_smile:

You either have to use the middleware method which puts Auth.js int he path of each request, or you can do something like (code not necessarily 100% accurate, but you get the idea):

import { auth } from "../../auth"

export async function POST () {
  const { data: session } = await auth()
  if (!session.user) {
    return Response.json({ message: "Not authenticated" }, { status: 401 })
  }
}
clieee commented 4 months ago

So, here is my current setup:

I've also created a local setup of Postgres.

src/app/api/auth/[...nextauth]/route.ts: export { GET, POST } from '@/auth';

src/auth.ts:

import { type Adapter } from '@auth/core/adapters';
import { PrismaAdapter } from '@auth/prisma-adapter';
import { PrismaClient } from '@prisma/client';
import NextAuth from 'next-auth';
import Google from 'next-auth/providers/google';

export const AUTH_MESSAGES = {
    INVALID_SESSION: 'Invalid session'
};

const prisma = new PrismaClient();

const adapter: Adapter = {
    ...PrismaAdapter(prisma)
};

export const {
    handlers: { GET, POST },
    auth
} = NextAuth({
    providers: [Google],
    adapter,
    session: {
        strategy: 'database',
        maxAge: 60 * 60 * 24 * 30
    },
    callbacks: {
        async session({ session, user }) {
            if (session.user) {
                session.user.id = user.id;
            }
            return session;
        }
    }
});

src/middleware.ts:

import { auth } from '@/auth';
import { NextResponse } from 'next/server';

export default auth((req) => {
    console.log('middleware auth check: ', req.auth);
    if (!req.auth) {
        return NextResponse.redirect(new URL('/api/auth/signin', req.url));
    }
});

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

When I navigate to for example "/" path, or any other paths in my project this is what error I'm getting: Error: PrismaClient is unable to run in Vercel Edge Functions or Edge Middleware. As an alternative, try Accelerate: https://pris.ly/d/accelerate.

Am I missing something?

ndom91 commented 4 months ago

Yeah so you also can't be doing any database actions in the middleware which is happening due to the fact that yuo've got the database session strategy selected. If yuo change this to "jwt" it should work with @prisma/client@5.9.1 and next-auth@5.0.0-beta.9. Also @auth/prisma-adapter is up to 1.3.3 now, I'd upgrade to that as well :+1:

qbounti commented 3 months ago

I had to comment out the second line for it to work for me (export const runtime = "edge"; // optional)

image
anisriaz commented 3 months ago

any one solve this issue [auth][error] AdapterError: Read more at https://errors.authjs.dev#adaptererror

Invalid prisma.account.create() invocation:

ndom91 commented 3 months ago

any one solve this issue [auth][error] AdapterError: Read more at https://errors.authjs.dev#adaptererror

Invalid prisma.account.create() invocation:

Sounds like an issue with your prisma data. Are you modifying the user / account in the callbacks in your auth config?

Please share more details like your config and versions used 👍

petejodo commented 3 months ago

Does anyone know what the immutable error means. I'm trying to test what happens when my callback throws and following the next-auth code, it seems to be doing the right thing with throwing a CallbackError but that then leads to this error in Nextjs and it's not completely clear why

ndom91 commented 2 months ago

Prisma posted about new edge support in preview in 5.11.0+

https://www.prisma.io/blog/prisma-orm-support-for-edge-functions-is-now-in-preview

qbounti commented 2 months ago

Awesome, thanks for the update!

On Tue, Mar 19, 2024 at 3:37 PM Nico Domino @.***> wrote:

Prisma posted about new edge support in preview in 5.11.0+

https://www.prisma.io/blog/prisma-orm-support-for-edge-functions-is-now-in-preview

— Reply to this email directly, view it on GitHub https://github.com/nextauthjs/next-auth/issues/9300#issuecomment-2007976099, or unsubscribe https://github.com/notifications/unsubscribe-auth/A2EMG2ULTQGJPDXUKA6Y67LYZCHXLAVCNFSM6AAAAABAD4VC66VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDAMBXHE3TMMBZHE . You are receiving this because you commented.Message ID: @.***>

A1X5H04 commented 2 months ago

I am getting the same immutable error but with Drizzle ORM

beegdady commented 2 months ago

This error occurs because NextAuth is Edge compatible, but some of the database adapters, such as Prisma, are not. If any of your files are configured to have a runtime on Edge, you'll likely encounter this error.

The solution is to locate the route.ts file in your app/api/[...nextauth] folder and set the runtime to nodejs or completely remove the runtime variable from your route.ts file.

Your app/api/auth/[...nextauth]/route.ts should resemble the following:

export { GET, POST } from "@/auth"; export const runtime = "nodejs"; // You can optionally remove this, but if it's set to 'edge', there will be an error when using edge incompatible adapters.

abutahermuhammad commented 4 weeks ago

This edge (serverless) incompatibility issue can be solved with driverAdaptors.

Here I am using neon for PostgreSQL:


// auth.ts file
import { PrismaAdapter } from "@auth/prisma-adapter";
import { PrismaNeon } from "@prisma/adapter-neon";
import { Pool } from "@neondatabase/serverless";
import { PrismaClient } from "@prisma/client";

const neon = new Pool({
  connectionString: process.env.POSTGRES_PRISMA_URL,
});
const adapter = new PrismaNeon(neon);
const prisma = new PrismaClient({ adapter });

export const { handlers, auth, signIn, signOut } = NextAuth({
  adapter: PrismaAdapter(prisma),
  // Other auth configs.
}
``
ndom91 commented 4 weeks ago

Hey y'all, we recently added a guide on this edge compatibility issue from a very general that explains the problem, etc. and then hopefully gives some useful tips and a workaround.

https://authjs.dev/guides/edge-compatibility

I'm going to close this issue because we seem to have gotten to the bottom of the issue here and know what to do, etc.

For prisma specific questions, check out their new edge deploy docs: https://www.prisma.io/docs/orm/prisma-client/deployment/edge/overview

Sammk21 commented 3 weeks ago

I had to comment out the second line for it to work for me (export const runtime = "edge"; // optional)

image

this works