[GH-ISSUE #6233] CLI generates duplicate Prisma indexes #10455

Closed
opened 2026-04-13 06:36:56 -05:00 by GiteaMirror · 2 comments
Owner

Originally created by @ceolinwill on GitHub (Nov 23, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/6233

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Add the Prisma adapter
  2. Run the CLI with the following command: pnpm dlx @better-auth/cli@latest generate to generate the Prisma schema for the first time
  3. Run the CLI again to update the Prisma schema

Current vs. Expected behavior

Current behavior:

Each run adds the same index again.

Expected behavior:

The CLI should detect existing indexes and avoid writing duplicates.

What version of Better Auth are you using?

1.4.1

System info

{
  "system": {
    "platform": "darwin",
    "arch": "arm64",
    "version": "Darwin Kernel Version 25.1.0: Mon Oct 20 19:32:56 PDT 2025; root:xnu-12377.41.6~2/RELEASE_ARM64_T8132",
    "release": "25.1.0",
    "cpuCount": 10,
    "cpuModel": "Apple M4",
    "totalMemory": "16.00 GB",
    "freeMemory": "0.07 GB"
  },
  "node": {
    "version": "v22.21.1",
    "env": "development"
  },
  "packageManager": {
    "name": "pnpm",
    "version": "10.23.0"
  },
  "frameworks": null,
  "databases": null,
  "betterAuth": {
    "version": "1.4.1",
    "config": {
      "account": {
        "accountLinking": {
          "enabled": true
        }
      },
      "experimental": {
        "joins": true
      },
      "plugins": [
        {
          "name": "next-cookies",
          "config": {
            "id": "next-cookies",
            "hooks": {
              "after": [
                {}
              ]
            }
          }
        },
        {
          "name": "admin",
          "config": {
            "id": "admin",
            "hooks": {
              "after": [
                {}
              ]
            },
            "endpoints": {},
            "$ERROR_CODES": {
              "FAILED_TO_CREATE_USER": "Failed to create user",
              "USER_ALREADY_EXISTS": "User already exists.",
              "USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL": "User already exists. Use another email.",
              "YOU_CANNOT_BAN_YOURSELF": "You cannot ban yourself",
              "YOU_ARE_NOT_ALLOWED_TO_CHANGE_USERS_ROLE": "You are not allowed to change users role",
              "YOU_ARE_NOT_ALLOWED_TO_CREATE_USERS": "You are not allowed to create users",
              "YOU_ARE_NOT_ALLOWED_TO_LIST_USERS": "You are not allowed to list users",
              "YOU_ARE_NOT_ALLOWED_TO_LIST_USERS_SESSIONS": "You are not allowed to list users sessions",
              "YOU_ARE_NOT_ALLOWED_TO_BAN_USERS": "You are not allowed to ban users",
              "YOU_ARE_NOT_ALLOWED_TO_IMPERSONATE_USERS": "You are not allowed to impersonate users",
              "YOU_ARE_NOT_ALLOWED_TO_REVOKE_USERS_SESSIONS": "You are not allowed to revoke users sessions",
              "YOU_ARE_NOT_ALLOWED_TO_DELETE_USERS": "You are not allowed to delete users",
              "YOU_ARE_NOT_ALLOWED_TO_SET_USERS_PASSWORD": "[REDACTED]",
              "BANNED_USER": "You have been banned from this application",
              "YOU_ARE_NOT_ALLOWED_TO_GET_USER": "You are not allowed to get user",
              "NO_DATA_TO_UPDATE": "No data to update",
              "YOU_ARE_NOT_ALLOWED_TO_UPDATE_USERS": "You are not allowed to update users",
              "YOU_CANNOT_REMOVE_YOURSELF": "You cannot remove yourself",
              "YOU_ARE_NOT_ALLOWED_TO_SET_NON_EXISTENT_VALUE": "You are not allowed to set a non-existent role value"
            },
            "schema": {
              "user": {
                "fields": {
                  "role": {
                    "type": "string",
                    "required": false,
                    "input": false
                  },
                  "banned": {
                    "type": "boolean",
                    "defaultValue": false,
                    "required": false,
                    "input": false
                  },
                  "banReason": {
                    "type": "string",
                    "required": false,
                    "input": false
                  },
                  "banExpires": {
                    "type": "date",
                    "required": false,
                    "input": false
                  }
                }
              },
              "session": {
                "fields": {
                  "impersonatedBy": {
                    "type": "string",
                    "required": false
                  }
                }
              }
            }
          }
        },
        {
          "name": "email-otp",
          "config": {
            "id": "email-otp",
            "endpoints": {},
            "hooks": {
              "after": [
                {}
              ]
            },
            "$ERROR_CODES": {
              "OTP_EXPIRED": "OTP expired",
              "INVALID_OTP": "Invalid OTP",
              "TOO_MANY_ATTEMPTS": "Too many attempts"
            },
            "rateLimit": [
              {
                "window": 60,
                "max": 3
              },
              {
                "window": 60,
                "max": 3
              },
              {
                "window": 60,
                "max": 3
              },
              {
                "window": 60,
                "max": 3
              }
            ]
          }
        },
        {
          "name": "stripe",
          "config": {
            "id": "stripe",
            "endpoints": {},
            "schema": {
              "subscription": {
                "fields": {
                  "plan": {
                    "type": "string",
                    "required": true
                  },
                  "referenceId": {
                    "type": "string",
                    "required": true
                  },
                  "stripeCustomerId": {
                    "type": "string",
                    "required": false
                  },
                  "stripeSubscriptionId": {
                    "type": "string",
                    "required": false
                  },
                  "status": {
                    "type": "string",
                    "defaultValue": "incomplete"
                  },
                  "periodStart": {
                    "type": "date",
                    "required": false
                  },
                  "periodEnd": {
                    "type": "date",
                    "required": false
                  },
                  "trialStart": {
                    "type": "date",
                    "required": false
                  },
                  "trialEnd": {
                    "type": "date",
                    "required": false
                  },
                  "cancelAtPeriodEnd": {
                    "type": "boolean",
                    "required": false,
                    "defaultValue": false
                  },
                  "seats": {
                    "type": "number",
                    "required": false
                  }
                }
              },
              "user": {
                "fields": {
                  "stripeCustomerId": {
                    "type": "string",
                    "required": false
                  }
                }
              }
            },
            "$ERROR_CODES": {
              "SUBSCRIPTION_NOT_FOUND": "Subscription not found",
              "SUBSCRIPTION_PLAN_NOT_FOUND": "Subscription plan not found",
              "ALREADY_SUBSCRIBED_PLAN": "You're already subscribed to this plan",
              "UNABLE_TO_CREATE_CUSTOMER": "Unable to create customer",
              "FAILED_TO_FETCH_PLANS": "Failed to fetch plans",
              "EMAIL_VERIFICATION_REQUIRED": "Email verification is required before you can subscribe to a plan",
              "SUBSCRIPTION_NOT_ACTIVE": "Subscription is not active",
              "SUBSCRIPTION_NOT_SCHEDULED_FOR_CANCELLATION": "Subscription is not scheduled for cancellation"
            }
          }
        }
      ],
      "rateLimit": {
        "enabled": true,
        "storage": "database"
      },
      "session": {
        "cookieCache": {
          "enabled": true,
          "maxAge": 3600
        },
        "expiresIn": 2592000
      },
      "socialProviders": {},
      "trustedOrigins": [
        "https://appleid.apple.com"
      ]
    }
  }
}

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

Other

Auth config (if applicable)


Additional context

No response

Originally created by @ceolinwill on GitHub (Nov 23, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/6233 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1. Add the Prisma adapter 2. Run the CLI with the following command: `pnpm dlx @better-auth/cli@latest generate` to generate the Prisma schema for the first time 3. Run the CLI again to update the Prisma schema ### Current vs. Expected behavior **Current behavior:** Each run adds the same index again. **Expected behavior:** The CLI should detect existing indexes and avoid writing duplicates. ### What version of Better Auth are you using? 1.4.1 ### System info ```bash { "system": { "platform": "darwin", "arch": "arm64", "version": "Darwin Kernel Version 25.1.0: Mon Oct 20 19:32:56 PDT 2025; root:xnu-12377.41.6~2/RELEASE_ARM64_T8132", "release": "25.1.0", "cpuCount": 10, "cpuModel": "Apple M4", "totalMemory": "16.00 GB", "freeMemory": "0.07 GB" }, "node": { "version": "v22.21.1", "env": "development" }, "packageManager": { "name": "pnpm", "version": "10.23.0" }, "frameworks": null, "databases": null, "betterAuth": { "version": "1.4.1", "config": { "account": { "accountLinking": { "enabled": true } }, "experimental": { "joins": true }, "plugins": [ { "name": "next-cookies", "config": { "id": "next-cookies", "hooks": { "after": [ {} ] } } }, { "name": "admin", "config": { "id": "admin", "hooks": { "after": [ {} ] }, "endpoints": {}, "$ERROR_CODES": { "FAILED_TO_CREATE_USER": "Failed to create user", "USER_ALREADY_EXISTS": "User already exists.", "USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL": "User already exists. Use another email.", "YOU_CANNOT_BAN_YOURSELF": "You cannot ban yourself", "YOU_ARE_NOT_ALLOWED_TO_CHANGE_USERS_ROLE": "You are not allowed to change users role", "YOU_ARE_NOT_ALLOWED_TO_CREATE_USERS": "You are not allowed to create users", "YOU_ARE_NOT_ALLOWED_TO_LIST_USERS": "You are not allowed to list users", "YOU_ARE_NOT_ALLOWED_TO_LIST_USERS_SESSIONS": "You are not allowed to list users sessions", "YOU_ARE_NOT_ALLOWED_TO_BAN_USERS": "You are not allowed to ban users", "YOU_ARE_NOT_ALLOWED_TO_IMPERSONATE_USERS": "You are not allowed to impersonate users", "YOU_ARE_NOT_ALLOWED_TO_REVOKE_USERS_SESSIONS": "You are not allowed to revoke users sessions", "YOU_ARE_NOT_ALLOWED_TO_DELETE_USERS": "You are not allowed to delete users", "YOU_ARE_NOT_ALLOWED_TO_SET_USERS_PASSWORD": "[REDACTED]", "BANNED_USER": "You have been banned from this application", "YOU_ARE_NOT_ALLOWED_TO_GET_USER": "You are not allowed to get user", "NO_DATA_TO_UPDATE": "No data to update", "YOU_ARE_NOT_ALLOWED_TO_UPDATE_USERS": "You are not allowed to update users", "YOU_CANNOT_REMOVE_YOURSELF": "You cannot remove yourself", "YOU_ARE_NOT_ALLOWED_TO_SET_NON_EXISTENT_VALUE": "You are not allowed to set a non-existent role value" }, "schema": { "user": { "fields": { "role": { "type": "string", "required": false, "input": false }, "banned": { "type": "boolean", "defaultValue": false, "required": false, "input": false }, "banReason": { "type": "string", "required": false, "input": false }, "banExpires": { "type": "date", "required": false, "input": false } } }, "session": { "fields": { "impersonatedBy": { "type": "string", "required": false } } } } } }, { "name": "email-otp", "config": { "id": "email-otp", "endpoints": {}, "hooks": { "after": [ {} ] }, "$ERROR_CODES": { "OTP_EXPIRED": "OTP expired", "INVALID_OTP": "Invalid OTP", "TOO_MANY_ATTEMPTS": "Too many attempts" }, "rateLimit": [ { "window": 60, "max": 3 }, { "window": 60, "max": 3 }, { "window": 60, "max": 3 }, { "window": 60, "max": 3 } ] } }, { "name": "stripe", "config": { "id": "stripe", "endpoints": {}, "schema": { "subscription": { "fields": { "plan": { "type": "string", "required": true }, "referenceId": { "type": "string", "required": true }, "stripeCustomerId": { "type": "string", "required": false }, "stripeSubscriptionId": { "type": "string", "required": false }, "status": { "type": "string", "defaultValue": "incomplete" }, "periodStart": { "type": "date", "required": false }, "periodEnd": { "type": "date", "required": false }, "trialStart": { "type": "date", "required": false }, "trialEnd": { "type": "date", "required": false }, "cancelAtPeriodEnd": { "type": "boolean", "required": false, "defaultValue": false }, "seats": { "type": "number", "required": false } } }, "user": { "fields": { "stripeCustomerId": { "type": "string", "required": false } } } }, "$ERROR_CODES": { "SUBSCRIPTION_NOT_FOUND": "Subscription not found", "SUBSCRIPTION_PLAN_NOT_FOUND": "Subscription plan not found", "ALREADY_SUBSCRIBED_PLAN": "You're already subscribed to this plan", "UNABLE_TO_CREATE_CUSTOMER": "Unable to create customer", "FAILED_TO_FETCH_PLANS": "Failed to fetch plans", "EMAIL_VERIFICATION_REQUIRED": "Email verification is required before you can subscribe to a plan", "SUBSCRIPTION_NOT_ACTIVE": "Subscription is not active", "SUBSCRIPTION_NOT_SCHEDULED_FOR_CANCELLATION": "Subscription is not scheduled for cancellation" } } } ], "rateLimit": { "enabled": true, "storage": "database" }, "session": { "cookieCache": { "enabled": true, "maxAge": 3600 }, "expiresIn": 2592000 }, "socialProviders": {}, "trustedOrigins": [ "https://appleid.apple.com" ] } } } ``` ### Which area(s) are affected? (Select all that apply) Other ### Auth config (if applicable) ```typescript ``` ### Additional context _No response_
GiteaMirror added the lockedbug labels 2026-04-13 06:36:56 -05:00
Author
Owner

@better-auth-agent[bot] commented on GitHub (Nov 23, 2025):

Thanks for raising this issue regarding duplicate Prisma indexes when running the CLI multiple times. It appears that when you run the generate command repeatedly, the tool is not checking for existing indexes before appending new ones. Since you're using version 1.4.1, please verify that your CLI is up-to-date and consider manually cleaning the schema as a temporary workaround. We’re actively looking into a fix so that subsequent runs detect and avoid duplicate indexes. If you have additional details or specific edge cases, please share them so we can further reproduce the behavior. Tag @better-auth-agent if you would like an answer from the Agent. What additional context or logs can you provide to help us better understand the situation?

DiagramDiscordGitHub

Diagram Join Star

<!-- gh-comment-id:3568022036 --> @better-auth-agent[bot] commented on GitHub (Nov 23, 2025): Thanks for raising this issue regarding duplicate Prisma indexes when running the CLI multiple times. It appears that when you run the generate command repeatedly, the tool is not checking for existing indexes before appending new ones. Since you're using version 1.4.1, please verify that your CLI is up-to-date and consider manually cleaning the schema as a temporary workaround. We’re actively looking into a fix so that subsequent runs detect and avoid duplicate indexes. If you have additional details or specific edge cases, please share them so we can further reproduce the behavior. Tag @better-auth-agent if you would like an answer from the Agent. What additional context or logs can you provide to help us better understand the situation? <!-- bot:webhook reply v1 --> [Diagram](https://repodiagrams.s3.eu-north-1.amazonaws.com/better-auth_ultra_detailed_interactive.html) • [Discord](https://discord.gg/better-auth) • [GitHub](https://github.com/better-auth/better-auth) [![Diagram](https://img.shields.io/badge/Diagram-2b3137?style=flat-square)](https://repodiagrams.s3.eu-north-1.amazonaws.com/better-auth_ultra_detailed_interactive.html) [![Join](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&style=flat-square)](https://discord.gg/better-auth) [![Star](https://img.shields.io/badge/star-181717?logo=github&logoColor=white&style=flat-square)](https://github.com/better-auth/better-auth)
Author
Owner

@dosubot[bot] commented on GitHub (Nov 23, 2025):

This is a known limitation in the current Better Auth CLI: it does not check for existing Prisma index block attributes before adding new ones, so running the CLI multiple times will append duplicate indexes to your schema. The relevant logic is in the Prisma schema generator, which unconditionally adds index attributes for each indexed field on every run without deduplication checks (source).

Recent updates (like the auto-indexing feature in PR #5357) improved index handling, but as of now, manual cleanup is required: after generating your schema, remove any duplicate @@index blocks before running Prisma migrations (source).

Until a fix is released, the recommended workaround is to manually edit your Prisma schema after each generation to ensure there are no duplicate indexes.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

<!-- gh-comment-id:3568023945 --> @dosubot[bot] commented on GitHub (Nov 23, 2025): <!-- Answer --> This is a known limitation in the current Better Auth CLI: it does not check for existing Prisma index block attributes before adding new ones, so running the CLI multiple times will append duplicate indexes to your schema. The relevant logic is in the Prisma schema generator, which unconditionally adds index attributes for each indexed field on every run without deduplication checks [(source)](https://github.com/better-auth/better-auth/blob/a378f81517bc6c2a6871212f2c5fc2ee72c0a95c/packages/cli/src/generators/prisma.ts#L19-L414). Recent updates (like the auto-indexing feature in PR #5357) improved index handling, but as of now, manual cleanup is required: after generating your schema, remove any duplicate @@index blocks before running Prisma migrations [(source)](https://github.com/better-auth/better-auth/pull/5357). Until a fix is released, the recommended workaround is to manually edit your Prisma schema after each generation to ensure there are no duplicate indexes. <!-- 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/ea82959d-e90b-48c3-8474-a65534db27ac?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/ea82959d-e90b-48c3-8474-a65534db27ac?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/ea82959d-e90b-48c3-8474-a65534db27ac?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/ea82959d-e90b-48c3-8474-a65534db27ac?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/ea82959d-e90b-48c3-8474-a65534db27ac?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/ea82959d-e90b-48c3-8474-a65534db27ac?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/ea82959d-e90b-48c3-8474-a65534db27ac?feedback_type=other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=This%20is%20a%20known%20limitation%20in%20the%20current%20Better%20Auth%20CLI%3A%20it%20does%20not%20check%20for%20existing%20Prisma%20index%20block%20attributes%20before%20adding%20new%20ones%2C%20so%20running%20the%20CLI%20multiple%20times%20will%20append%20duplicate%20indexes%20to%20your%20schema.%20The%20relevant%20logic%20is%20in%20the%20Prisma%20schema%20generator%2C%20which%20unconditionally%20adds%20index%20attributes%20for%20each%20indexed%20field%20on%20every%20run%20without%20deduplication%20checks%20%5B%28source%29%5D%28https%3A//github.com/better-auth/better-auth/blob/a378f81517bc6c2a6871212f2c5fc2ee72c0a95c/packages/cli/src/generators/prisma.ts%23L19-L414%29.%0A%0ARecent%20updates%20%28like%20the%20auto-indexing%20feature%20in%20PR%20%235357%29%20improved%20index%20handling%2C%20but%20as%20of%20now%2C%20manual%20cleanup%20is%20required%3A%20after%20generating%20your%20schema%2C%20remove%20any%20duplicate%20%40%40index%20blocks%20before%20running%20Prisma%20migrations%20%5B%28source%29%5D%28https%3A//github.com/better-auth/better-auth/pull/5357%29.%0A%0AUntil%20a%20fix%20is%20released%2C%20the%20recommended%20workaround%20is%20to%20manually%20edit%20your%20Prisma%20schema%20after%20each%20generation%20to%20ensure%20there%20are%20no%20duplicate%20indexes.)&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/6233)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#10455