next-auth icon indicating copy to clipboard operation
next-auth copied to clipboard

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

Open riccardolinares opened this issue 1 year ago • 22 comments

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:

  • Runtime Environment: The project is built on Next.js version 14, specifically using the Runtime Edge configuration.
  • Error Description: The error associated with the Prisma Adapter surfaces randomly during a user's session. Once it appears, it persists and affects the user experience.
  • Temporary Resolution: The only way I have found to temporarily resolve the issue is by clearing the application's cache and deleting the .next folder. Then after a few minutes I am able to login again... However, this is not a viable long-term solution.

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"

riccardolinares avatar Dec 02 '23 09:12 riccardolinares

I have this issue too

DarKS4ys avatar Dec 03 '23 17:12 DarKS4ys

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 avatar Dec 04 '23 10:12 riccardolinares

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

riccardolinares avatar Dec 04 '23 10:12 riccardolinares

I'm facing the same error right now.

harisrab avatar Dec 08 '23 13:12 harisrab

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

taylor-lindores-reeves avatar Dec 11 '23 13:12 taylor-lindores-reeves

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

franfdezmorales avatar Dec 11 '23 15:12 franfdezmorales

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

snilan avatar Dec 12 '23 23:12 snilan

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

taylor-lindores-reeves avatar Dec 12 '23 23:12 taylor-lindores-reeves

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

snilan avatar Dec 13 '23 00:12 snilan

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.

martinzlocha avatar Dec 18 '23 13:12 martinzlocha

``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 ?

gagandua078 avatar Dec 27 '23 05:12 gagandua078

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 avatar Jan 07 '24 17:01 MilanObrenovic

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 avatar Jan 07 '24 20:01 MilanObrenovic

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

MilanObrenovic avatar Jan 08 '24 01:01 MilanObrenovic

[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:

  • 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!

clkefe avatar Jan 11 '24 14:01 clkefe

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

LegendNihal avatar Jan 18 '24 16:01 LegendNihal

@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 :)

clkefe avatar Jan 18 '24 21:01 clkefe

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

ndom91 avatar Feb 03 '24 14:02 ndom91

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?

clieee avatar Feb 08 '24 07:02 clieee

So Prisma's just shipped an update that handles htis a bit more gracefully. Can you give @prisma/[email protected] 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 })
  }
}

ndom91 avatar Feb 08 '24 18:02 ndom91

So, here is my current setup:

  • "next": "14.1.0"
  • "next-auth": "^5.0.0-beta.5"
  • "@prisma/client": "^5.9.1"
  • "@auth/prisma-adapter": "^1.2.1"

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?

clieee avatar Feb 09 '24 08:02 clieee

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/[email protected] and [email protected]. Also @auth/prisma-adapter is up to 1.3.3 now, I'd upgrade to that as well :+1:

ndom91 avatar Feb 10 '24 00:02 ndom91

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

image

qbounti avatar Feb 21 '24 22:02 qbounti

any one solve this issue [auth][error] AdapterError: Read more at https://errors.authjs.dev#adaptererror [auth][cause]: PrismaClientValidationError: Invalid prisma.account.create() invocation:

anisriaz avatar Mar 13 '24 18:03 anisriaz

any one solve this issue [auth][error] AdapterError: Read more at https://errors.authjs.dev#adaptererror [auth][cause]: PrismaClientValidationError: 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 👍

ndom91 avatar Mar 14 '24 10:03 ndom91

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

petejodo avatar Mar 15 '24 13:03 petejodo

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

ndom91 avatar Mar 19 '24 19:03 ndom91

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: @.***>

qbounti avatar Mar 21 '24 23:03 qbounti

I am getting the same immutable error but with Drizzle ORM

A1X5H04 avatar Mar 23 '24 09:03 A1X5H04

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.

beegdady avatar Mar 29 '24 05:03 beegdady