List users query with plus sign fails #2148

Closed
opened 2026-03-13 09:30:28 -05:00 by GiteaMirror · 1 comment
Owner

Originally created by @jefflang80 on GitHub (Oct 18, 2025).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

GET /admin/list-users docs

Returns 0 results when email has a plus sign ('+').

MongoDB contains...

[
  {name: "jeff", email: "jeff@email.com", role: "user"},
  {name: "jeff one", email: "jeff+one@gmail.com", role: "user"},
]
const getUser(email: string, headers: any) {
       const userResult = await auth.api.listUsers({
                headers: headers,
                query: {
                    searchField: 'email',
                    searchValue: email,
                    searchOperator: 'contains',
                    limit: '1',
                }
        });
        return userResult.users;
}

getUser("jeff@email.com", headers);
[{name: "jeff", email: "jeff@email.com", role: "user"}]
getUser("jeff+one@email.com", headers);
[]

Current vs. Expected behavior

Queries with a plus sign in the email should return matching addresses

What version of Better Auth are you using?

1.3.7

System info

{
  "system": {
    "platform": "darwin",
    "arch": "arm64",
    "version": "Darwin Kernel Version 25.0.0: Wed Sep 17 21:41:23 PDT 2025; root:xnu-12377.1.9~141/RELEASE_ARM64_T8122",
    "release": "25.0.0",
    "cpuCount": 8,
    "cpuModel": "Apple M3",
    "totalMemory": "24.00 GB",
    "freeMemory": "0.36 GB"
  },
  "node": {
    "version": "v23.8.0",
    "env": "development"
  },
  "packageManager": {
    "name": "npm",
    "version": "11.3.0"
  },
  "frameworks": [
    {
      "name": "express",
      "version": "^4.18.1"
    }
  ],
  "databases": null,
  "betterAuth": {
    "version": "^1.3.7",
    "config": {
      "emailAndPassword": {
        "enabled": true,
        "autoSignIn": true,
        "requireEmailVerification": true,
        "minPasswordLength": 6,
        "maxPasswordLength": 32
      },
      "emailVerification": {
        "autoSignInAfterVerification": 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. 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",
              "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": "email-otp",
          "config": {
            "id": "email-otp",
            "endpoints": {},
            "hooks": {
              "after": [
                {}
              ]
            },
            "$ERROR_CODES": {
              "OTP_EXPIRED": "otp expired",
              "INVALID_OTP": "Invalid OTP",
              "INVALID_EMAIL": "Invalid email",
              "USER_NOT_FOUND": "User not found",
              "TOO_MANY_ATTEMPTS": "Too many attempts"
            },
            "rateLimit": [
              {
                "window": 60,
                "max": 3
              },
              {
                "window": 60,
                "max": 3
              },
              {
                "window": 60,
                "max": 3
              },
              {
                "window": 60,
                "max": 3
              }
            ]
          }
        }
      ],
      "session": {
        "expiresIn": 86400,
        "updateAge": 43200,
        "cookieCache": {
          "enabled": true,
          "maxAge": 604800
        }
      },
      "advanced": {
        "crossSubDomainCookies": {
          "enabled": false
        },
        "useSecureCookies": false,
        "defaultCookieAttributes": {
          "httpOnly": true,
          "secure": false
        }
      },
      "user": {
        "additionalFields": {
          "isActive": {
            "type": "boolean",
            "required": false
          },
          "lastLogin": {
            "type": "date",
            "required": false
          },
          "provider": {
            "type": "string",
            "required": false
          },
          "providerId": {
            "type": "string",
            "required": false
          },
          "avatar": {
            "type": "string",
            "required": false
          }
        }
      },
      "rateLimit": {
        "window": 900,
        "max": 100
      },
      "secret": "[REDACTED]",
      "baseURL": "http://localhost:9600/",
      "basePath": "/auth",
      "trustedOrigins": [
        "http://localhost:3000",
        "http://localhost:3001",
        "http://localhost:9600/"
      ],
      "hooks": {}
    }
  }
}

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

Backend

Auth config (if applicable)


Additional context

No response

Originally created by @jefflang80 on GitHub (Oct 18, 2025). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce GET /admin/list-users [docs](https://www.better-auth.com/docs/plugins/admin#list-users) Returns 0 results when email has a plus sign ('+'). MongoDB contains... ``` [ {name: "jeff", email: "jeff@email.com", role: "user"}, {name: "jeff one", email: "jeff+one@gmail.com", role: "user"}, ] ``` ``` const getUser(email: string, headers: any) { const userResult = await auth.api.listUsers({ headers: headers, query: { searchField: 'email', searchValue: email, searchOperator: 'contains', limit: '1', } }); return userResult.users; } ``` `getUser("jeff@email.com", headers); ` [{name: "jeff", email: "jeff@email.com", role: "user"}] `getUser("jeff+one@email.com", headers); ` [] ### Current vs. Expected behavior Queries with a plus sign in the email should return matching addresses ### What version of Better Auth are you using? 1.3.7 ### System info ```bash { "system": { "platform": "darwin", "arch": "arm64", "version": "Darwin Kernel Version 25.0.0: Wed Sep 17 21:41:23 PDT 2025; root:xnu-12377.1.9~141/RELEASE_ARM64_T8122", "release": "25.0.0", "cpuCount": 8, "cpuModel": "Apple M3", "totalMemory": "24.00 GB", "freeMemory": "0.36 GB" }, "node": { "version": "v23.8.0", "env": "development" }, "packageManager": { "name": "npm", "version": "11.3.0" }, "frameworks": [ { "name": "express", "version": "^4.18.1" } ], "databases": null, "betterAuth": { "version": "^1.3.7", "config": { "emailAndPassword": { "enabled": true, "autoSignIn": true, "requireEmailVerification": true, "minPasswordLength": 6, "maxPasswordLength": 32 }, "emailVerification": { "autoSignInAfterVerification": 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. 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", "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": "email-otp", "config": { "id": "email-otp", "endpoints": {}, "hooks": { "after": [ {} ] }, "$ERROR_CODES": { "OTP_EXPIRED": "otp expired", "INVALID_OTP": "Invalid OTP", "INVALID_EMAIL": "Invalid email", "USER_NOT_FOUND": "User not found", "TOO_MANY_ATTEMPTS": "Too many attempts" }, "rateLimit": [ { "window": 60, "max": 3 }, { "window": 60, "max": 3 }, { "window": 60, "max": 3 }, { "window": 60, "max": 3 } ] } } ], "session": { "expiresIn": 86400, "updateAge": 43200, "cookieCache": { "enabled": true, "maxAge": 604800 } }, "advanced": { "crossSubDomainCookies": { "enabled": false }, "useSecureCookies": false, "defaultCookieAttributes": { "httpOnly": true, "secure": false } }, "user": { "additionalFields": { "isActive": { "type": "boolean", "required": false }, "lastLogin": { "type": "date", "required": false }, "provider": { "type": "string", "required": false }, "providerId": { "type": "string", "required": false }, "avatar": { "type": "string", "required": false } } }, "rateLimit": { "window": 900, "max": 100 }, "secret": "[REDACTED]", "baseURL": "http://localhost:9600/", "basePath": "/auth", "trustedOrigins": [ "http://localhost:3000", "http://localhost:3001", "http://localhost:9600/" ], "hooks": {} } } } ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript ``` ### Additional context _No response_
GiteaMirror added the bug label 2026-03-13 09:30:28 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Jan 17, 2026):

Hi, @jefflang80. I'm Dosu, and I'm helping the better-auth team manage their backlog and am marking this issue as stale.

Issue Summary

  • You reported that the listUsers query in Better Auth API version 1.3.7 does not return results when searching for emails containing a plus sign ('+').
  • Queries using the "contains" operator with emails like "jeff+one@gmail.com" yield no results, while emails without '+' return correctly.
  • This behavior suggests the API might not be handling special characters like '+' properly in search queries.
  • No further comments or updates have been provided since the initial report.

Next Steps

  • Please let me know if this issue is still relevant with the latest version of better-auth by commenting here.
  • If I do not hear back within 7 days, this issue will be automatically closed.

Thank you for your understanding and contribution!

@dosubot[bot] commented on GitHub (Jan 17, 2026): Hi, @jefflang80. I'm [Dosu](https://dosu.dev), and I'm helping the better-auth team manage their backlog and am marking this issue as stale. **Issue Summary** - You reported that the `listUsers` query in Better Auth API version 1.3.7 does not return results when searching for emails containing a plus sign ('+'). - Queries using the "contains" operator with emails like "jeff+one@gmail.com" yield no results, while emails without '+' return correctly. - This behavior suggests the API might not be handling special characters like '+' properly in search queries. - No further comments or updates have been provided since the initial report. **Next Steps** - Please let me know if this issue is still relevant with the latest version of better-auth by commenting here. - If I do not hear back within 7 days, this issue will be automatically closed. Thank you for your understanding and contribution!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#2148