nextauthjs / next-auth

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

Invalid `p.account.findUnique()` invocation with prisma #3815

Closed MattA-Official closed 2 years ago

MattA-Official commented 2 years ago

Title

Invalid p.account.findUnique() invocation with prisma

How to reproduce ☕️

next-auth: 4.0.0-beta.7 @next-auth/prisma-adapter: 0.5.2-next.19

/pages/api/[...nextauth].ts

import { PrismaAdapter } from '@next-auth/prisma-adapter';
import { hasBetaAccess } from 'lib/backend-utils';
import { prisma } from 'lib/prisma';
import NextAuth from 'next-auth';
import Discord from 'next-auth/providers/discord';

export default NextAuth({
  adapter: PrismaAdapter(prisma),
  providers: [
    Discord({
      clientId: process.env.CLIENT_ID,
      clientSecret: process.env.CLIENT_SECRET,
      authorization: 'https://discord.com/api/oauth2/authorize?scope=identify+guilds',
      profile(profile) {
        let image_url: string;

        if (profile.avatar === null) {
          const defaultAvatarNumber = parseInt(profile.discriminator, 10) % 5;
          image_url = `https://cdn.discordapp.com/embed/avatars/${defaultAvatarNumber}.png`;
        } else {
          const format = profile.avatar.startsWith('a_') ? 'gif' : 'png';
          image_url = `https://cdn.discordapp.com/avatars/${profile.id}/${profile.avatar}.${format}`;
        }

        return {
          id: profile.id,
          username: profile.username,
          discriminator: profile.discriminator,
          avatar: image_url,
          profile: {
            vanity: profile.id,
            user_id: profile.id,
          },
        };
      },
    }),
  ],
  callbacks: {
    async session({ session, user }) {
      return {
        ...session,
        user,
      };
    },
    async signIn({ user }) {
      // Check for a development environment
      if (process.env.NODE_ENV === 'development') return true;

      // Check if the user has access to the beta
      const betaUser = user.beta || (await hasBetaAccess(user.id));
      return betaUser ? true : '/?error=AccessDenied';
    },
  },
});

Account schema

model Account {
  id                 String  @id @default(cuid()) @map("_id")
  userId             String  @map("user_id")
  type               String
  provider           String
  providerAccountId  String  @map("provider_account_id")
  refresh_token      String?
  access_token       String?
  expires_at         Int?
  token_type         String?
  scope              String?
  id_token           String?
  session_state      String?

  user User @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@unique([provider, providerAccountId])
  @@map("accounts")
}

Your question/bug report 📓

The bug below results from the above code. It is worth noting I am using MongoDB and not any sort of SQL.

Invalid `p.account.findUnique()` invocation in
C:\Users\folder\path\node_modules\@next-auth\prisma-adapter\dist\index.js:11:45

   8 getUserByEmail: (email) => p.user.findUnique({ where: { email } }),
   9 async getUserByAccount(provider_providerAccountId) {
  10     var _a;
→ 11     const account = await p.account.findUnique({
           where: {
             provider_providerAccountId: {
             ~~~~~~~~~~~~~~~~~~~~~~~~~~
               providerAccountId: '366652352125599744',
               provider: 'discord'
             }
           },
           select: {
             user: true
           }
         })

Unknown arg `provider_providerAccountId` in where.provider_providerAccountId for type AccountWhereUniqueInput. Available args:

type AccountWhereUniqueInput {
  id?: String
}

Contributing 🙌🏽

Yes, I am

bassem97 commented 1 year ago

@bassem97 Will do. When you say you "found it on [your] own." Where did you find it? I imagine not just trial and error lol. Curious what resources your looking at. Maybe I can learn something from your process 💪

When i said "found it on my own " i meant that i didn't found it on google or smthg , to simplify the process i can say that the final schema i got it after many tentatives, every time i change a value and see the output/error and so on, if you wanna talk about it more you can dm me on one of my socials in my github profile

sonipranjal commented 1 year ago

Thanks, @bassem97, Your solution works!

It took almost one year to find the solution to this issue lol

bassem97 commented 1 year ago

@sonipranjal glad to hear this 🙏🥳

atlas700 commented 1 year ago

@bassem97 Tnx man!

bassem97 commented 1 year ago

@bassem97 Tnx man!

You're welcome !!

pedrolucasfv commented 1 year ago

You're welcome !!

YOU ARE GOD MY FRIEND, I FIXED MY PROBLEM WITH THIS CODE, BEAUTIFUL, PERFECT, THE BEST!!!!!!!!!!!!!!

Zeyu-Li commented 1 year ago

I still get issues sometimes, what is the exact issue with this?

qhkm commented 1 year ago

@Zeyu-Li

Account
  provider           String
  providerAccountId  String    @map("provider_account_id")

  @@unique([provider, providerAccountId])

This part is what solves the issue. This mapping is needed to resolve the issue

bassem97 commented 1 year ago

You're welcome !!

YOU ARE GOD MY FRIEND, I FIXED MY PROBLEM WITH THIS CODE, BEAUTIFUL, PERFECT, THE BEST!!!!!!!!!!!!!!

Glad it worked !!!!!! you're welcome

pksingh-sme commented 1 year ago

Add "@map("provider_account_id")" in model Account for field

providerAccountId String @map("provider_account_id")

samgable27 commented 1 year ago

problem solved by modifying prisma schema to this:

model User {
  id                    String     @id @default(uuid())
  name                  String
  email                 String?    @unique
  emailVerified         DateTime?   @map("email_verified")
  image                 String?
  createdAt             DateTime   @default(now())
  updatedAt             DateTime   @updatedAt
  accounts              Account[]
  sessions              Session[]
  @@map("users")
}
model Account {
  id                 String    @id @default(cuid())
  userId              String    @map("user_id")
  type                 String?
  provider           String
  providerAccountId  String    @map("provider_account_id")
  token_type         String?
  refresh_token      String?   @db.Text
  access_token       String?   @db.Text
  expires_at         Int?
  scope              String?
  id_token           String? @db.Text
  createdAt          DateTime  @default(now())
  updatedAt          DateTime  @updatedAt
  user               User      @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@unique([provider, providerAccountId])
  @@map("accounts")
}

model Session {
  id           String   @id @default(cuid())
  userId       String?  @map("user_id")
  sessionToken String   @db.Text @map("session_token") @unique
  accessToken  String?  @db.Text @map("access_token")
  expires      DateTime
  user         User?     @relation(fields: [userId], references: [id], onDelete: Cascade)
  createdAt    DateTime @default(now())
  updatedAt    DateTime @updatedAt

  @@map("sessions")
}

model VerificationRequest {
  id         String   @id @default(cuid())
  identifier String
  token      String   @unique
  expires    DateTime
  createdAt  DateTime @default(now())
  updatedAt  DateTime @updatedAt

  @@unique([identifier, token])
}

then execute npx prisma db push to apply schema changes to remote db

bro THANK YOU!!!!!!!

bassem97 commented 1 year ago

problem solved by modifying prisma schema to this:

model User {
  id                    String     @id @default(uuid())
  name                  String
  email                 String?    @unique
  emailVerified         DateTime?   @map("email_verified")
  image                 String?
  createdAt             DateTime   @default(now())
  updatedAt             DateTime   @updatedAt
  accounts              Account[]
  sessions              Session[]
  @@map("users")
}
model Account {
  id                 String    @id @default(cuid())
  userId              String    @map("user_id")
  type                 String?
  provider           String
  providerAccountId  String    @map("provider_account_id")
  token_type         String?
  refresh_token      String?   @db.Text
  access_token       String?   @db.Text
  expires_at         Int?
  scope              String?
  id_token           String? @db.Text
  createdAt          DateTime  @default(now())
  updatedAt          DateTime  @updatedAt
  user               User      @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@unique([provider, providerAccountId])
  @@map("accounts")
}

model Session {
  id           String   @id @default(cuid())
  userId       String?  @map("user_id")
  sessionToken String   @db.Text @map("session_token") @unique
  accessToken  String?  @db.Text @map("access_token")
  expires      DateTime
  user         User?     @relation(fields: [userId], references: [id], onDelete: Cascade)
  createdAt    DateTime @default(now())
  updatedAt    DateTime @updatedAt

  @@map("sessions")
}

model VerificationRequest {
  id         String   @id @default(cuid())
  identifier String
  token      String   @unique
  expires    DateTime
  createdAt  DateTime @default(now())
  updatedAt  DateTime @updatedAt

  @@unique([identifier, token])
}

then execute npx prisma db push to apply schema changes to remote db

bro THANK YOU!!!!!!!

@samgable27 you're welcome 🎆

janusqa commented 1 year ago

sessionToken String @unique @map("session_token") @db.Text This line is producing the following error

Error: Prisma schema validation - (validate wasm)
Error code: P1012
error: Native type `Text` cannot be unique in MySQL. Please use the `length` argument to the field in the index definition to allow this.
bassem97 commented 1 year ago

sessionToken String @unique @map("session_token") @db.Text This line is producing the following error

Error: Prisma schema validation - (validate wasm)
Error code: P1012
error: Native type `Text` cannot be unique in MySQL. Please use the `length` argument to the field in the index definition to allow this.

@janusqa can you first inverse the order of @db.text and @unique , then verify Prisma version: sessionToken String @db.Text @map("session_token") @unique

janusqa commented 1 year ago

sessionToken String @unique @map("session_token") @db.Text This line is producing the following error

Error: Prisma schema validation - (validate wasm)
Error code: P1012
error: Native type `Text` cannot be unique in MySQL. Please use the `length` argument to the field in the index definition to allow this.

@janusqa can you first inverse the order of @db.text and @unique , then verify Prisma version: sessionToken String @db.Text @map("session_token") @unique

@bassem97

"@prisma/client": "^5.3.1",
"prisma": "^5.3.1",

Saving the schema file automatically inverted the order for me already.

bassem97 commented 1 year ago

"prisma":

@janusqa can you please switch to v5.2.0 and see if the problem persist ?

janusqa commented 1 year ago

@bassem97 It's still there in 5.2.0 as far as I see. Note to make the error go away I have just dropped the @db.Text Maybe this is unique to mySql

I found this https://github.com/prisma/prisma/issues/8661 It makes sense to me too to change the db.Text to db.varchar()

  sessionToken String   @unique @map("session_token") @db.VarChar(191)

and specify the max length of what the session token should be like 191

bassem97 commented 1 year ago

@bassem97 It's still there in 5.2.0 as far as I see. Note to make the error go away I have just dropped the @db.Text Maybe this is unique to mySql

I found this prisma/prisma#8661 It makes sense to me too to change the db.Text to db.varchar()

  sessionToken String   @unique @map("session_token") @db.VarChar(191)

and specify the max length of what the session token should be like 191

@janusqa i would recommend doing that if i knew that you are using MySQL and not Postgres, glad it worked anyways !

utkarshkhanna2609 commented 1 year ago

next-auth][error][OAUTH_CALLBACK_HANDLER_ERROR] https://next-auth.js.org/errors#oauth_callback_handler_error Invalid prisma.account.findUnique() invocation:

error: Error validating datasource db: the URL must start with the protocol mysql://. --> schema.prisma:7 6 provider = "mysql" 7 url = env("DATABASE_URL")

Validation Error Count: 1 PrismaClientInitializationError: Invalid prisma.account.findUnique() invocation:

error: Error validating datasource db: the URL must start with the protocol mysql://. --> schema.prisma:7 6 provider = "mysql" 7 url = env("DATABASE_URL")

Validation Error Count: 1 name: 'GetUserByAccountError', code: undefined }

I was facing this issue too, turns out, the environment variable of my planetscale db url was incorrect, hope this helps!

devwax commented 9 months ago

Regenerating the Prisma client fixed it for me.

npx prisma generate

I had been working with and merging an older branch of the app. That may have caused it.

I had also run npm run build a few times recently while troubleshooting deployment errors locally. Not sure if that can necessitate a prisma client rebuild. Anyway, I would definitely try it. An easy fix for a perplexing problem.

fjdkslvn commented 6 months ago

@bassem97 @janusqa Thanks to you two, the problem was easily resolved. Thank you ㅠㅠㅠ

jahangeer7704 commented 5 months ago

model Account { id String @id @default(auto()) @Map("_id") @db.ObjectId userId String @db.ObjectId type String? provider String? providerAccountId String? refresh_token String? @db.String access_token String? @db.String expires_at Int? token_type String? scope String? id_token String? @db.String session_state String?

createdAt DateTime @default(now()) updatedAt DateTime @updatedAt

user User @relation(fields: [userId], references: [id], onDelete: Cascade)

@https://github.com/unique([provider, providerAccountId]) } i made my model like this ,the issue gone

SavixDR commented 4 months ago

@bassem97 Thanks brother. ❤️ you're a lifesaver ❤️‍🔥

congduong97 commented 2 months ago

@Zeyu-Li

Account
  provider           String
  providerAccountId  String    @map("provider_account_id")

  @@unique([provider, providerAccountId])

This part is what solves the issue. This mapping is needed to resolve the issue

It works for me,Thanks