[GH-ISSUE #3158] api-key update not working #18128

Closed
opened 2026-04-15 16:30:44 -05:00 by GiteaMirror · 7 comments
Owner

Originally created by @johanwilson on GitHub (Jun 24, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/3158

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Setup better auth with prisma and the apiKey plugin
  2. Call the API key update endpoint with keyId.
  3. Observe the Prisma error about needing a unique identifier.

Current vs. Expected behavior

When calling db[model].update() in the Prisma adapter, the where clause is constructed with an AND array containing both id and userId. Prisma's update method requires a unique identifier (such as just id), and using an AND clause results in the following error:

Invalid `db[model].update()` invocation...
Argument `where` of type ApikeyWhereUniqueInput needs at least one of `id` arguments.

This prevents updating API keys by keyId.

The update should succeed when passing a keyId.

What version of Better Auth are you using?

1.2.10

Provide environment information

- OS: Windows 11
- Browser: Chrome
- Runtime: node 22.13.0, bun 1.2.17

Which area(s) are affected? (Select all that apply)

Client, Backend

Auth config (if applicable)

export const auth = betterAuth({
  database: prismaAdapter(prisma, {
    provider: "postgresql",
  }),
  plugins: [
    apiKey({
      apiKeyHeaders: ["x-api-key"],
    }),
  ],
});

Additional context

Using better-auth with Prisma adapter (PSQL) in a Next.js project.

Looks like a few other plugins have the same issue with the AND clause causing Prisma to believe that it is not a unique where input.

#2474

Originally created by @johanwilson on GitHub (Jun 24, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/3158 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1. Setup better auth with prisma and the `apiKey` plugin 2. Call the API key update endpoint with `keyId`. 3. Observe the Prisma error about needing a unique identifier. ### Current vs. Expected behavior When calling `db[model].update()` in the Prisma adapter, the `where` clause is constructed with an `AND` array containing both `id` and `userId`. Prisma's `update` method requires a unique identifier (such as just `id`), and using an `AND` clause results in the following error: ``` Invalid `db[model].update()` invocation... Argument `where` of type ApikeyWhereUniqueInput needs at least one of `id` arguments. ``` This prevents updating API keys by keyId. The update should succeed when passing a keyId. ### What version of Better Auth are you using? 1.2.10 ### Provide environment information ```bash - OS: Windows 11 - Browser: Chrome - Runtime: node 22.13.0, bun 1.2.17 ``` ### Which area(s) are affected? (Select all that apply) Client, Backend ### Auth config (if applicable) ```typescript export const auth = betterAuth({ database: prismaAdapter(prisma, { provider: "postgresql", }), plugins: [ apiKey({ apiKeyHeaders: ["x-api-key"], }), ], }); ``` ### Additional context Using better-auth with Prisma adapter (PSQL) in a Next.js project. Looks like a few other plugins have the same issue with the AND clause causing Prisma to believe that it is not a unique where input. #2474
GiteaMirror added the locked label 2026-04-15 16:30:44 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Jun 24, 2025):

Hi @johanwilson! I'm Dosu and I’m helping the better-auth team.

The error happens because the Prisma adapter in better-auth constructs the where clause for updates using an AND array (e.g., both id and userId), but Prisma requires a unique identifier (like just id) for update operations. When the where clause isn't uniquely identifying, Prisma throws the error you saw. This pattern can affect other plugins too, not just the API key plugin.

The fix should be in the Prisma adapter: for update operations, the where clause should only use the unique identifier field (usually id) instead of an AND array. The adapter currently generalizes for multiple backends, but Prisma's update method is stricter and needs a unique key in the where clause. No recent pull requests directly address this for updates—most focus on other clause handling or unrelated improvements (source).

Workaround:
If you need an immediate fix, you can patch your local Prisma adapter to ensure that, for updates, the where clause only includes the unique identifier. Look for the update logic in your adapter and adjust it to use { id: keyId } for API key updates.

This is a targeted change and should resolve the error for API key updates and any other plugin/model with a similar pattern.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Join Discord Share on X

<!-- gh-comment-id:2999968798 --> @dosubot[bot] commented on GitHub (Jun 24, 2025): <!-- Greeting --> Hi @johanwilson! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> The error happens because the Prisma adapter in better-auth constructs the where clause for updates using an AND array (e.g., both `id` and `userId`), but Prisma requires a unique identifier (like just `id`) for update operations. When the where clause isn't uniquely identifying, Prisma throws the error you saw. This pattern can affect other plugins too, not just the API key plugin. The fix should be in the Prisma adapter: for update operations, the where clause should only use the unique identifier field (usually `id`) instead of an AND array. The adapter currently generalizes for multiple backends, but Prisma's update method is stricter and needs a unique key in the where clause. No recent pull requests directly address this for updates—most focus on other clause handling or unrelated improvements ([source](https://github.com/better-auth/better-auth/pull/2874)). **Workaround:** If you need an immediate fix, you can patch your local Prisma adapter to ensure that, for updates, the where clause only includes the unique identifier. Look for the update logic in your adapter and adjust it to use `{ id: keyId }` for API key updates. This is a targeted change and should resolve the error for API key updates and any other plugin/model with a similar pattern. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/23bef984-d670-402c-91f6-e3089a3ce672?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/23bef984-d670-402c-91f6-e3089a3ce672?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/23bef984-d670-402c-91f6-e3089a3ce672?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/23bef984-d670-402c-91f6-e3089a3ce672?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/23bef984-d670-402c-91f6-e3089a3ce672?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/23bef984-d670-402c-91f6-e3089a3ce672?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/23bef984-d670-402c-91f6-e3089a3ce672?feedback_type=other)</sup>&nbsp;&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/issues/3158)
Author
Owner

@Kinfe123 commented on GitHub (Jun 25, 2025):

have you generated the schema and sync your db ?

<!-- gh-comment-id:3005935538 --> @Kinfe123 commented on GitHub (Jun 25, 2025): have you generated the schema and sync your db ?
Author
Owner

@johanwilson commented on GitHub (Jun 25, 2025):

Yes, it's up to date

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

generator client {
  provider            = "prisma-client"
  binaryTargets       = ["native", "rhel-openssl-1.1.x"]
  previewFeatures     = ["views", "relationJoins", "nativeDistinct", "typedSql"]
  output              = "../generated/prisma"
  moduleFormat        = "esm"
  importFileExtension = ""
}

...

model Apikey {
  id                  String    @id @default(ulid())
  name                String?
  start               String?
  prefix              String?
  key                 String
  userId              String
  user                User      @relation(fields: [userId], references: [id], onDelete: Cascade)
  refillInterval      Int?
  refillAmount        Int?
  lastRefillAt        DateTime?
  enabled             Boolean?
  rateLimitEnabled    Boolean?
  rateLimitTimeWindow Int?
  rateLimitMax        Int?
  requestCount        Int?
  remaining           Int?
  lastRequest         DateTime?
  expiresAt           DateTime?
  createdAt           DateTime  @default(now())
  updatedAt           DateTime  @default(now()) @updatedAt
  permissions         String?
  metadata            String?

  @@map("apikey")
}

Adapter query and raw error.

"Invalid `db[model].update()` invocation in
C:\...\node_modules\better-auth\dist\adapters\prisma-adapter\index.mjs:147:32

  144   );
  145 }
  146 const whereClause = convertWhereClause(model, where);
→ 147 return await db[model].update({
        where: {
          AND: [
            {
              id: "01JYMB3DN522TQSFNW475T34T5"
            },
            {
              userId: "fbT2XzkUstliuoVE83jBcm1YiALhU2ag"
            }
          ],
      ?   id?: String,
      ?   OR?: ApikeyWhereInput[],
      ?   NOT?: ApikeyWhereInput | ApikeyWhereInput[],
      ?   name?: StringNullableFilter | String | Null,
      ?   start?: StringNullableFilter | String | Null,
      ?   prefix?: StringNullableFilter | String | Null,
      ?   key?: StringFilter | String,
      ?   userId?: StringFilter | String,
      ?   refillInterval?: IntNullableFilter | Int | Null,
      ?   refillAmount?: IntNullableFilter | Int | Null,
      ?   lastRefillAt?: DateTimeNullableFilter | DateTime | Null,
      ?   enabled?: BoolNullableFilter | Boolean | Null,
      ?   rateLimitEnabled?: BoolNullableFilter | Boolean | Null,
      ?   rateLimitTimeWindow?: IntNullableFilter | Int | Null,
      ?   rateLimitMax?: IntNullableFilter | Int | Null,
      ?   requestCount?: IntNullableFilter | Int | Null,
      ?   remaining?: IntNullableFilter | Int | Null,
      ?   lastRequest?: DateTimeNullableFilter | DateTime | Null,
      ?   expiresAt?: DateTimeNullableFilter | DateTime | Null,
      ?   createdAt?: DateTimeFilter | DateTime,
      ?   updatedAt?: DateTimeFilter | DateTime,
      ?   permissions?: StringNullableFilter | String | Null,
      ?   metadata?: StringNullableFilter | String | Null,
      ?   user?: UserScalarRelationFilter | UserWhereInput
        },
        data: {
          enabled: false,
          remaining: null,
          lastRequest: new Date("2025-06-25T20:07:16.204Z")
        }
      })

Argument `where` of type ApikeyWhereUniqueInput needs at least one of `id` arguments. Available options are marked with ?."

if i try to run the query directly, same error is produced , Argument where of type ApikeyWhereUniqueInput needs at least one of id arguments

async function testQuery() {
  await prisma.apikey.update({
    where: {
      AND: [
        {
          id: "01JYMB3DN522TQSFNW475T34T5",
        },
        {
          userId: "fbT2XzkUstliuoVE83jBcm1YiALhU2ag",
        },
      ],
    },
    data: {
      enabled: false,
      remaining: null,
      lastRequest: new Date("2025-06-25T20:07:16.204Z"),
    },
  });
}
<!-- gh-comment-id:3006025041 --> @johanwilson commented on GitHub (Jun 25, 2025): Yes, it's up to date ```prisma datasource db { provider = "postgresql" url = env("DATABASE_URL") } generator client { provider = "prisma-client" binaryTargets = ["native", "rhel-openssl-1.1.x"] previewFeatures = ["views", "relationJoins", "nativeDistinct", "typedSql"] output = "../generated/prisma" moduleFormat = "esm" importFileExtension = "" } ... model Apikey { id String @id @default(ulid()) name String? start String? prefix String? key String userId String user User @relation(fields: [userId], references: [id], onDelete: Cascade) refillInterval Int? refillAmount Int? lastRefillAt DateTime? enabled Boolean? rateLimitEnabled Boolean? rateLimitTimeWindow Int? rateLimitMax Int? requestCount Int? remaining Int? lastRequest DateTime? expiresAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @default(now()) @updatedAt permissions String? metadata String? @@map("apikey") } ``` Adapter query and raw error. ```typescript "Invalid `db[model].update()` invocation in C:\...\node_modules\better-auth\dist\adapters\prisma-adapter\index.mjs:147:32 144 ); 145 } 146 const whereClause = convertWhereClause(model, where); → 147 return await db[model].update({ where: { AND: [ { id: "01JYMB3DN522TQSFNW475T34T5" }, { userId: "fbT2XzkUstliuoVE83jBcm1YiALhU2ag" } ], ? id?: String, ? OR?: ApikeyWhereInput[], ? NOT?: ApikeyWhereInput | ApikeyWhereInput[], ? name?: StringNullableFilter | String | Null, ? start?: StringNullableFilter | String | Null, ? prefix?: StringNullableFilter | String | Null, ? key?: StringFilter | String, ? userId?: StringFilter | String, ? refillInterval?: IntNullableFilter | Int | Null, ? refillAmount?: IntNullableFilter | Int | Null, ? lastRefillAt?: DateTimeNullableFilter | DateTime | Null, ? enabled?: BoolNullableFilter | Boolean | Null, ? rateLimitEnabled?: BoolNullableFilter | Boolean | Null, ? rateLimitTimeWindow?: IntNullableFilter | Int | Null, ? rateLimitMax?: IntNullableFilter | Int | Null, ? requestCount?: IntNullableFilter | Int | Null, ? remaining?: IntNullableFilter | Int | Null, ? lastRequest?: DateTimeNullableFilter | DateTime | Null, ? expiresAt?: DateTimeNullableFilter | DateTime | Null, ? createdAt?: DateTimeFilter | DateTime, ? updatedAt?: DateTimeFilter | DateTime, ? permissions?: StringNullableFilter | String | Null, ? metadata?: StringNullableFilter | String | Null, ? user?: UserScalarRelationFilter | UserWhereInput }, data: { enabled: false, remaining: null, lastRequest: new Date("2025-06-25T20:07:16.204Z") } }) Argument `where` of type ApikeyWhereUniqueInput needs at least one of `id` arguments. Available options are marked with ?." ``` if i try to run the query directly, same error is produced , Argument `where` of type ApikeyWhereUniqueInput needs at least one of `id` arguments ```typescript async function testQuery() { await prisma.apikey.update({ where: { AND: [ { id: "01JYMB3DN522TQSFNW475T34T5", }, { userId: "fbT2XzkUstliuoVE83jBcm1YiALhU2ag", }, ], }, data: { enabled: false, remaining: null, lastRequest: new Date("2025-06-25T20:07:16.204Z"), }, }); }
Author
Owner

@Kinfe123 commented on GitHub (Jun 25, 2025):

the thing the update prisma api is receiving a compound where clauses. we either should do updateMany or remove userId field since api key is retrieved userId for future we make sure the update api receives a unique id field with the where clause.

<!-- gh-comment-id:3006228594 --> @Kinfe123 commented on GitHub (Jun 25, 2025): the thing the `update` prisma api is receiving a compound where clauses. we either should do `updateMany` or remove userId field since api key is retrieved `userId` for future we make sure the `update` api receives a unique id field with the where clause.
Author
Owner

@Kinfe123 commented on GitHub (Jun 25, 2025):

can you try installing this and see if that fixes your issue -

npm i https://pkg.pr.new/better-auth/better-auth@3174
<!-- gh-comment-id:3006232493 --> @Kinfe123 commented on GitHub (Jun 25, 2025): can you try installing this and see if that fixes your issue - ```ts npm i https://pkg.pr.new/better-auth/better-auth@3174 ```
Author
Owner

@Diegoescalonaro commented on GitHub (Mar 15, 2026):

can you try installing this and see if that fixes your issue -

npm i https://pkg.pr.new/better-auth/better-auth@3174

This worked for me, is it already added to any of the latest releases?

<!-- gh-comment-id:4062686557 --> @Diegoescalonaro commented on GitHub (Mar 15, 2026): > can you try installing this and see if that fixes your issue - > > npm i https://pkg.pr.new/better-auth/better-auth@3174 This worked for me, is it already added to any of the latest releases?
Author
Owner

@github-actions[bot] commented on GitHub (Mar 31, 2026):

This issue has been locked as it was closed more than 7 days ago. If you're experiencing a similar problem or you have additional context, please open a new issue and reference this one.

<!-- gh-comment-id:4165919395 --> @github-actions[bot] commented on GitHub (Mar 31, 2026): This issue has been locked as it was closed more than 7 days ago. If you're experiencing a similar problem or you have additional context, please open a new issue and reference this one.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#18128