使用Next.js13.4、NextAuth与Prisma Adapter时GetUserByAccountError报错求助
问题:NextAuth + Prisma Adapter 社交登录触发GetUserByAccountError错误
错误详情
Unknown arg `provider_providerAccountId` in where.provider_providerAccountId for type AccountWhereUniqueInput. Did you mean `providerId_providerAccountId`? Available args: type AccountWhereUniqueInput { id?: String providerId_providerAccountId?: AccountProviderId_providerAccountIdCompoundUniqueInput } Error: Invalid `prisma.account.findUnique()` invocation: { where: { provider_providerAccountId: { ~~~~~~~~~~~~~~~~~~~~~~~~~~ providerAccountId: '100794952997699653180', provider: 'google' } }, select: { user: true } } Unknown arg `provider_providerAccountId` in where.provider_providerAccountId for type AccountWhereUniqueInput. Did you mean `providerId_providerAccountId`? Available args: type AccountWhereUniqueInput { id?: String providerId_providerAccountId?: AccountProviderId_providerAccountIdCompoundUniqueInput } at Ai.validate (C:\Users\Heiner\chatgpt\frontend\node_modules\@prisma\client\runtime\library.js:144:73) at un.createMessage (C:\Users\Heiner\chatgpt\frontend\node_modules\@prisma\client\runtime\library.js:161:1298) at C:\Users\Heiner\chatgpt\frontend\node_modules\@prisma\client\runtime\library.js:174:10818 at Object.runInChildSpan (C:\Users\Heiner\chatgpt\frontend\node_modules\@prisma\client\runtime\library.js:171:1343) at t._executeRequest (C:\Users\Heiner\chatgpt\frontend\node_modules\@prisma\client\runtime\library.js:174:10795) at async getUserByAccount (webpack-internal:///(sc_server)/./node_modules/@next-auth/prisma-adapter/dist/index.js:224:29) { name: 'GetUserByAccountError', code: undefined }
已尝试操作
- 检查Prisma Studio正常运行
- 确认数据库已完成正确迁移
复现代码
app/api/auth/[...nextauth]/route.ts
import { Session } from "next-auth" import NextAuth from "next-auth/next" import GoogleProvider from "next-auth/providers/google" import { PrismaAdapter } from "@next-auth/prisma-adapter" import bcrypt from "bcrypt" import GithubProvider from "next-auth/providers/github" import CredentialsProvider from "next-auth/providers/credentials" import { PrismaClient } from "@prisma/client" const prisma = new PrismaClient() const handler = NextAuth({ adapter: PrismaAdapter(prisma), providers: [ GithubProvider({ name: "github", clientId: process.env.GITHUB_CLIENT_ID as string, clientSecret: process.env.GITHUB_CLIENT_SECRET as string, }), GoogleProvider({ name: "google", clientId: process.env.GOOGLE_CLIENT_ID as string, clientSecret: process.env.GOOGLE_CLIENT_SECRET as string, }), CredentialsProvider({ name: "credentials", credentials: { email: { label: "email", type: "email" }, password: { label: "password", type: "password" }, }, async authorize(credentials) { if (!credentials?.email || !credentials?.password) throw new Error("Invalid credentials") try { const user = await prisma.user.findFirst({ where: { email: credentials.email }, }) if (!user || !user?.hashedPassword) throw new Error("Invalid credentials") const isValid = await bcrypt.compare( credentials.password, user.hashedPassword ) if (!isValid) throw new Error("Invalid credentials") return user } catch (e: any) { throw new Error("Invalid credentials") } }, }), ], debug: process.env.NODE_ENV === "development", session: { strategy: "jwt", }, secret: process.env.NEXTAUTH_SECRET as string, }) export { handler as GET, handler as POST }
schema.prisma
// 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 = "postgresql" url = env("DATABASE_URL") } model User { id String @id @default(cuid()) name String? hashedPassword String? email String? @unique emailVerified DateTime? image String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt accounts Account[] sessions Session[] Post Post[] Comment Comment[] Like Like[] @@map(name: "user") } model Post { id Int @id @default(autoincrement()) image String caption String? createdAt DateTime @default(now()) userId String user User @relation(fields: [userId], references: [id]) comments Comment[] likes Like[] } model Comment { id Int @id @default(autoincrement()) text String createdAt DateTime @default(now()) userId String postId Int user User @relation(fields: [userId], references: [id]) post Post @relation(fields: [postId], references: [id]) } model Like { id Int @id @default(autoincrement()) userId String postId Int user User @relation(fields: [userId], references: [id]) post Post @relation(fields: [postId], references: [id]) } model Account { id String @id @default(cuid()) userId String providerType String providerId String providerAccountId String refreshToken String? accessToken String? accessTokenExpires DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id]) @@unique([providerId, providerAccountId], name: "providerId_providerAccountId") @@map(name: "account") } model Session { id String @id @default(cuid()) userId String expires DateTime sessionToken String @unique accessToken String @unique createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id]) } model VerificationRequest { id String @id @default(cuid()) identifier String token String @unique expires DateTime createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@unique([identifier, token]) }
问题成因
你的Prisma Account模型字段与@next-auth/prisma-adapter的默认期望不匹配:
- Adapter默认使用
provider字段标识登录服务商(如google/github),但你的模型中用的是providerId - Adapter默认使用
type字段标识登录类型,你的模型中用的是providerType - Adapter查询时会使用复合唯一键
provider_providerAccountId,但你的模型中定义的复合键是providerId_providerAccountId
这种字段名不匹配导致Adapter调用Prisma Client时传入了错误的查询参数,触发了GetUserByAccountError。
解决办法
方案一:修改Prisma Schema对齐Adapter要求
调整Account模型的字段名和复合键,与Adapter默认期望一致:
model Account { id String @id @default(cuid()) userId String type String // 替换原providerType provider String // 替换原providerId providerAccountId String refreshToken String? accessToken String? accessTokenExpires DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id]) @@unique([provider, providerAccountId], name: "provider_providerAccountId") // 对齐Adapter的复合键名称 @@map(name: "account") }
修改完成后执行以下命令:
npx prisma migrate dev npx prisma generate
方案二:自定义Adapter重写查询逻辑
如果不想修改现有数据库结构,可以自定义Adapter,重写getUserByAccount方法,使用你模型中的正确字段:
import { PrismaAdapter } from "@next-auth/prisma-adapter" import { PrismaClient } from "@prisma/client" const prisma = new PrismaClient() const customAdapter = { ...PrismaAdapter(prisma), async getUserByAccount(account) { return prisma.user.findUnique({ where: { accounts: { some: { providerId: account.provider, providerAccountId: account.providerAccountId, }, }, }, }) }, } // 在NextAuth配置中使用customAdapter const handler = NextAuth({ adapter: customAdapter, // 其他配置... })
内容的提问来源于stack exchange,提问作者codingIsLove
相关产品推荐
相关产品推荐

