[GH-ISSUE #5355] 2fa plugin does not work with drizzle if the user table is renamed #10219

Closed
opened 2026-04-13 06:12:18 -05:00 by GiteaMirror · 4 comments
Owner

Originally created by @scesbron on GitHub (Oct 16, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/5355

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

Here is a repo to reproduce the problem: https://github.com/scesbron/solid-auth

  1. Install the app with "pnpm install"
  2. create a ".env" file and add a "POSTGRESQL_URL=postgresql://..." line
  3. Run the migration with "pnpm run db:migrate"
  4. Launch the app with "pnpm run dev"
  5. Create a user
  6. Login with this user
  7. On the home page click on "Activation de la double authentication"
  8. In the activation page, enter the password and hit the button
  9. On the server we have the error " ERROR [Better Auth]: The field "userId" does not exist in the schema for the model "twoFactor". Please update your schema."

Current vs. Expected behavior

The problem occurs because in the schema file the "user" table is renamed to "users". This is something allowed, in the "lib/auth.ts" file I specified the new name for the user table, this is correctly handled by better-auth core but not by the 2fa plugin.

The expected behavior here is to not have an error in the server

What version of Better Auth are you using?

1.3.27

System info

{
  "system": {
    "platform": "linux",
    "arch": "x64",
    "version": "#85-Ubuntu SMP PREEMPT_DYNAMIC Thu Sep 18 15:26:59 UTC 2025",
    "release": "6.8.0-85-generic",
    "cpuCount": 8,
    "cpuModel": "Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz",
    "totalMemory": "15.30 GB",
    "freeMemory": "2.80 GB"
  },
  "node": {
    "version": "v20.17.0",
    "env": "development"
  },
  "packageManager": {
    "name": "npm",
    "version": "10.8.2"
  },
  "frameworks": [
    {
      "name": "solid",
      "version": "1.9.7"
    }
  ],
  "databases": [
    {
      "name": "postgres",
      "version": "3.4.7"
    },
    {
      "name": "drizzle",
      "version": "0.44.6"
    }
  ],
  "betterAuth": {
    "version": "1.3.27",
    "config": {
      "secret": "[REDACTED]",
      "emailAndPassword": {
        "enabled": true
      },
      "plugins": [
        {
          "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"
            },
            "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": "two-factor",
          "config": {
            "id": "two-factor",
            "endpoints": {},
            "hooks": {
              "after": [
                {}
              ]
            },
            "schema": {
              "user": {
                "fields": {
                  "twoFactorEnabled": {
                    "type": "boolean",
                    "required": false,
                    "defaultValue": false,
                    "input": false
                  }
                }
              },
              "twoFactor": {
                "fields": {
                  "secret": {
                    "type": "string",
                    "required": true,
                    "returned": false
                  },
                  "backupCodes": {
                    "type": "string",
                    "required": true,
                    "returned": false
                  },
                  "userId": {
                    "type": "string",
                    "required": true,
                    "returned": false,
                    "references": {
                      "model": "user",
                      "field": "id"
                    }
                  }
                }
              }
            },
            "rateLimit": [
              {
                "window": 10,
                "max": 3
              }
            ],
            "$ERROR_CODES": {
              "OTP_NOT_ENABLED": "OTP not enabled",
              "OTP_HAS_EXPIRED": "OTP has expired",
              "TOTP_NOT_ENABLED": "TOTP not enabled",
              "TWO_FACTOR_NOT_ENABLED": "Two factor isn't enabled",
              "BACKUP_CODES_NOT_ENABLED": "Backup codes aren't enabled",
              "INVALID_BACKUP_CODE": "Invalid backup code",
              "INVALID_CODE": "Invalid code",
              "TOO_MANY_ATTEMPTS_REQUEST_NEW_CODE": "Too many attempts. Please request a new code.",
              "INVALID_TWO_FACTOR_COOKIE": "Invalid two factor cookie"
            }
          }
        }
      ]
    }
  }
}

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

Backend

Auth config (if applicable)


Additional context

No response

Originally created by @scesbron on GitHub (Oct 16, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/5355 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce Here is a repo to reproduce the problem: https://github.com/scesbron/solid-auth 1. Install the app with "pnpm install" 2. create a ".env" file and add a "POSTGRESQL_URL=postgresql://..." line 3. Run the migration with "pnpm run db:migrate" 4. Launch the app with "pnpm run dev" 5. Create a user 6. Login with this user 7. On the home page click on "Activation de la double authentication" 8. In the activation page, enter the password and hit the button 9. On the server we have the error " ERROR [Better Auth]: The field "userId" does not exist in the schema for the model "twoFactor". Please update your schema." ### Current vs. Expected behavior The problem occurs because in the schema file the "user" table is renamed to "users". This is something allowed, in the "lib/auth.ts" file I specified the new name for the user table, this is correctly handled by better-auth core but not by the 2fa plugin. The expected behavior here is to not have an error in the server ### What version of Better Auth are you using? 1.3.27 ### System info ```bash { "system": { "platform": "linux", "arch": "x64", "version": "#85-Ubuntu SMP PREEMPT_DYNAMIC Thu Sep 18 15:26:59 UTC 2025", "release": "6.8.0-85-generic", "cpuCount": 8, "cpuModel": "Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz", "totalMemory": "15.30 GB", "freeMemory": "2.80 GB" }, "node": { "version": "v20.17.0", "env": "development" }, "packageManager": { "name": "npm", "version": "10.8.2" }, "frameworks": [ { "name": "solid", "version": "1.9.7" } ], "databases": [ { "name": "postgres", "version": "3.4.7" }, { "name": "drizzle", "version": "0.44.6" } ], "betterAuth": { "version": "1.3.27", "config": { "secret": "[REDACTED]", "emailAndPassword": { "enabled": true }, "plugins": [ { "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" }, "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": "two-factor", "config": { "id": "two-factor", "endpoints": {}, "hooks": { "after": [ {} ] }, "schema": { "user": { "fields": { "twoFactorEnabled": { "type": "boolean", "required": false, "defaultValue": false, "input": false } } }, "twoFactor": { "fields": { "secret": { "type": "string", "required": true, "returned": false }, "backupCodes": { "type": "string", "required": true, "returned": false }, "userId": { "type": "string", "required": true, "returned": false, "references": { "model": "user", "field": "id" } } } } }, "rateLimit": [ { "window": 10, "max": 3 } ], "$ERROR_CODES": { "OTP_NOT_ENABLED": "OTP not enabled", "OTP_HAS_EXPIRED": "OTP has expired", "TOTP_NOT_ENABLED": "TOTP not enabled", "TWO_FACTOR_NOT_ENABLED": "Two factor isn't enabled", "BACKUP_CODES_NOT_ENABLED": "Backup codes aren't enabled", "INVALID_BACKUP_CODE": "Invalid backup code", "INVALID_CODE": "Invalid code", "TOO_MANY_ATTEMPTS_REQUEST_NEW_CODE": "Too many attempts. Please request a new code.", "INVALID_TWO_FACTOR_COOKIE": "Invalid two factor cookie" } } } ] } } } ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript ``` ### Additional context _No response_
GiteaMirror added the locked label 2026-04-13 06:12:18 -05:00
Author
Owner

@bytaesu commented on GitHub (Nov 9, 2025):

Hi @scesbron,

I checked the code you provided, and it turns out not to be a real bug. After correcting that part, I couldn’t reproduce the issue. If you have any questions about using Better Auth, feel free to join our Discord channel and ask!

Image
<!-- gh-comment-id:3507534888 --> @bytaesu commented on GitHub (Nov 9, 2025): Hi @scesbron, I checked the code you provided, and it turns out not to be a real bug. After correcting that part, I couldn’t reproduce the issue. If you have any questions about using Better Auth, feel free to join our [Discord channel](https://discord.gg/better-auth) and ask! <img width="645" height="695" alt="Image" src="https://github.com/user-attachments/assets/45c94297-141b-454d-9dbf-f0cee1251904" />
Author
Owner

@scesbron commented on GitHub (Nov 10, 2025):

From your message it's not clear to me what correction you did on my code. On my side I was not able to use the 2fa with a table named users so I renamed it to user.

<!-- gh-comment-id:3509944674 --> @scesbron commented on GitHub (Nov 10, 2025): From your message it's not clear to me what correction you did on my code. On my side I was not able to use the 2fa with a table named `users` so I renamed it to `user`.
Author
Owner

@bytaesu commented on GitHub (Nov 10, 2025):

From your message it's not clear to me what correction you did on my code. On my side I was not able to use the 2fa with a table named users so I renamed it to user.

You’re assigning the plugin to the schema..

<!-- gh-comment-id:3509954593 --> @bytaesu commented on GitHub (Nov 10, 2025): > From your message it's not clear to me what correction you did on my code. On my side I was not able to use the 2fa with a table named `users` so I renamed it to `user`. You’re assigning the plugin to the schema..
Author
Owner

@bytaesu commented on GitHub (Nov 10, 2025):

From your message it's not clear to me what correction you did on my code. On my side I was not able to use the 2fa with a table named users so I renamed it to user.

Changing users to user only renamed the object, not the actual table. For details, please see https://www.better-auth.com/docs/concepts/database#custom-table-names🙏

<!-- gh-comment-id:3509968028 --> @bytaesu commented on GitHub (Nov 10, 2025): > From your message it's not clear to me what correction you did on my code. On my side I was not able to use the 2fa with a table named `users` so I renamed it to `user`. Changing users to user only renamed the object, not the actual table. For details, please see https://www.better-auth.com/docs/concepts/database#custom-table-names🙏
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#10219