next-auth: Invalid `p.account.findUnique()` invocation with prisma

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

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 2
  • Comments: 70 (10 by maintainers)

Commits related to this issue

Most upvoted comments

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

I had this problem and resolved it by directly naming the unique constraint in the Account model:

model Account {
  //...
  @@unique([provider, providerAccountId], name: "provider_providerAccountId")
}

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

Add “@map(“provider_account_id”)” in model Account for field

providerAccountId String @map(“provider_account_id”)

@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

Similar issue with MySQL

message: "Cannot read property 'findUnique' of undefined",
  stack: "TypeError: Cannot read property 'findUnique' of undefined\n" +
    '    at getUserByAccount (.....\\node_modules\\@next-auth\\prisma-adapter\\dist\\index.js:12:45)

And this is the […nextauth].js config

import NextAuth from "next-auth/next";
import GithubProvider from "next-auth/providers/github"
import { PrismaAdapter } from "@next-auth/prisma-adapter";
import { PrismaClient } from "@prisma/client"

const prisma = new PrismaClient()


export default NextAuth({
    adapter: PrismaAdapter({ prisma }),
    providers: [
        GithubProvider({
            clientId: process.env.GITHUB_ID,
            clientSecret: process.env.GITHUB_SECRET
        })
    ],
    secret: process.env.SECRET
})

Any idea?

Hey so one small thing I noticed, the prisma client instance should be passed to the adapter directly as the first argument, not in an object. i.e.

adapter: PrismaAdapter(prisma)

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!

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

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 🎆

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

You’re welcome !!

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

@bassem97 Tnx man!

Thanks, @bassem97, Your solution works!

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

@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

@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 💪

@bassem97 I’m happy to make a PR to the next-auth docs, unless you want to do it, lmk: https://github.com/nextauthjs/next-auth/blob/d73812bce5f5dc2f3f8b839554fc66a41284be30/packages/adapter-prisma/src/index.ts#L45

I’m curious though if not the docs, where did you find or how did you work out this alternate (and functional) implementation? Obviously, you are correct, because your code works 😊 But I’m curious how/where you found this eg: “attribut providerAccountId in Account table should be mapped in the db like this “provided_account_id” and the sessionToken and so on” if not in the docs.

Thanks again!

This seems to work for me as well! Thanks a lot 🙏

@bassem97 can you please provide some more context as to what you did and why/how this resolves the issue? Specifically, why does this schema.prisma (the one your provided) work and the implementation provided in the official documentation does not? https://authjs.dev/reference/adapter/prisma

Thank you!

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

Everything was working fine. All of a sudden, I’m facing the same issue. Not sure how to solve it. I’m using Google, and Email Magic Link login.

Found out that this issue is related to #2803|Linking accounts.

Thanks @bassem97, it works!!

Glad to hear 😍

Thanks @bassem97, it works!!

This fixed for me (using google oauth + planetscale mysql) thanks

Similar issue with MySQL

message: "Cannot read property 'findUnique' of undefined",
  stack: "TypeError: Cannot read property 'findUnique' of undefined\n" +
    '    at getUserByAccount (.....\\node_modules\\@next-auth\\prisma-adapter\\dist\\index.js:12:45)


Essentially in the prisma adapter p.account is undefined for some reason.

This is the schema


// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
}

model Account {
  id                String  @id @default(cuid())
  userId            String
  type              String
  provider          String
  providerAccountId String
  refresh_token     String? @db.Text
  access_token      String? @db.Text
  expires_at        Int?
  token_type        String?
  scope             String?
  id_token          String? @db.Text
  session_state     String?

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

  @@unique([provider, providerAccountId])
}

model Session {
  id           String   @id @default(cuid())
  sessionToken String   @unique
  userId       String
  expires      DateTime
  user         User     @relation(fields: [userId], references: [id], onDelete: Cascade)
}

model User {
  id            String    @id @default(cuid())
  name          String?
  email         String?   @unique
  emailVerified DateTime?
  image         String?
  accounts      Account[]
  sessions      Session[]
}

model VerificationToken {
  identifier String
  token      String   @unique
  expires    DateTime

  @@unique([identifier, token])
}

And this is the […nextauth].js config

import NextAuth from "next-auth/next";
import GithubProvider from "next-auth/providers/github"
import { PrismaAdapter } from "@next-auth/prisma-adapter";
import { PrismaClient } from "@prisma/client"

const prisma = new PrismaClient()


export default NextAuth({
    adapter: PrismaAdapter({ prisma }),
    providers: [
        GithubProvider({
            clientId: process.env.GITHUB_ID,
            clientSecret: process.env.GITHUB_SECRET
        })
    ],
    secret: process.env.SECRET
})

Any idea?

@MattA-Official the crux of your issue seems to be the same, right? That @@unique([provider, providerAccountId]) isn’t being applied, so to speak.

I did some digging through the Prisma docs, and it seems in the case of MongoDB, you must create this @@unique compound index yourself - Prisma can’t/doesn’t (not sure) do it in Mongo yet.

See: https://www.prisma.io/docs/reference/api-reference/prisma-schema-reference#mongodb-4

Currently testing over on https://github.com/TeamDmod/dmod/tree/prisma, the entire codebase is a mess so it’s being rewritten. Just started work on integrating prisma as the ORM today.

I would be happy to help run some tests, and I will try to reproduce the issue in a clean project. I shall try without the mapping to snake_case tomorrow.