list users querying and filtering bug #2121

Closed
opened 2026-03-13 09:28:49 -05:00 by GiteaMirror · 7 comments
Owner

Originally created by @imornar on GitHub (Oct 14, 2025).

GET /admin/list-users docs

Having following dataset:

[
  {name: "mark jackson", email: "markjackson@gmail.com", role: "admin"},
  {name: "mark soberg", email: "marksoberg@admin.com", role: "admin"},
]

result for filter:
{filterValue : "admin", filterField : "role", filterOperator : "eq"}
result: 2 OK

result for search:
{searchValue: "mar", searchField: "email", searchOperator: "contains" }
result: 2 OK

Result for both:
{filterValue : "admin", filterField : "role", filterOperator : "eq", searchValue: "mar", searchField: "email", searchOperator: "contains" }
result: 0 NOT OK

I would expect that this SQL is used:

-- For filter only (role = admin)
SELECT * FROM users
WHERE role = 'admin';

-- For search only (email contains 'mar')
SELECT * FROM users
WHERE email LIKE '%mar%';

-- For both filter AND search combined
SELECT * FROM users
WHERE role = 'admin'
AND email LIKE '%mar%';

-- The combined query should return both records since they match both conditions:
-- 1. mark jackson: role=admin AND email contains 'mar'
-- 2. mark soberg: role=admin AND email contains 'mar'

I'm not sure is this expected behavior or not?

Originally created by @imornar on GitHub (Oct 14, 2025). GET `/admin/list-users` [docs](https://www.better-auth.com/docs/plugins/admin#list-users) Having following dataset: ``` [ {name: "mark jackson", email: "markjackson@gmail.com", role: "admin"}, {name: "mark soberg", email: "marksoberg@admin.com", role: "admin"}, ] ``` result for filter: `{filterValue : "admin", filterField : "role", filterOperator : "eq"}` result: 2 OK ✅ result for search: `{searchValue: "mar", searchField: "email", searchOperator: "contains" }` result: 2 OK ✅ Result for both: `{filterValue : "admin", filterField : "role", filterOperator : "eq", searchValue: "mar", searchField: "email", searchOperator: "contains" }` result: 0 NOT OK ❓ I would expect that this SQL is used: -- For filter only (role = admin) SELECT * FROM users WHERE role = 'admin'; -- For search only (email contains 'mar') SELECT * FROM users WHERE email LIKE '%mar%'; -- For both filter AND search combined SELECT * FROM users WHERE role = 'admin' AND email LIKE '%mar%'; -- The combined query should return both records since they match both conditions: -- 1. mark jackson: role=admin AND email contains 'mar' -- 2. mark soberg: role=admin AND email contains 'mar' I'm not sure is this expected behavior or not?
GiteaMirror added the bug label 2026-03-13 09:28:49 -05:00
Author
Owner

@Kinfe123 commented on GitHub (Oct 14, 2025):

can you please check if those data exists on your db. i have added a test replicating your filters and searches here - #5299

@Kinfe123 commented on GitHub (Oct 14, 2025): can you please check if those data exists on your db. i have added a test replicating your filters and searches here - #5299
Author
Owner

@biniam0 commented on GitHub (Oct 14, 2025):

Which database adapter were you using?

@biniam0 commented on GitHub (Oct 14, 2025): Which database adapter were you using?
Author
Owner

@Kinfe123 commented on GitHub (Oct 14, 2025):

it has sqlite by default. can you please send your auth config ?

@Kinfe123 commented on GitHub (Oct 14, 2025): it has sqlite by default. can you please send your auth config ?
Author
Owner

@imornar commented on GitHub (Oct 14, 2025):

Checked, data exists correctly in database, when using just filters, it works as expected, when using just searches, it work as expected, when I combine both, always empty array.

I'm using postgress with drizzle

import { drizzle } from "drizzle-orm/node-postgres";
import { schema } from "./schema";

export const db = drizzle({
  connection: process.env.DATABASE_URL || "",
  casing: "snake_case",
  schema,
});

with auth config

export const drizzleAdapterOptions: DrizzleAdapterConfig = {
  provider: "pg",
  schema: authSchema,
  usePlural: true,
};

export const authOptions = {
  appName: "AppName",
  database: drizzleAdapter(db, drizzleAdapterOptions),
  user: {
    additionalFields: {
      active: { type: "boolean", defaultValue: true },
      about: { type: "string", required: false },
      firstName: { type: "string", required: true, input: true },
      lastName: { type: "string", required: true },
      phone: { type: "string", required: true },
      addressLine1: { type: "string", required: false },
      addressLine2: { type: "string", required: false },
      city: { type: "string", required: false },
      state: { type: "string", required: false },
      zipCode: { type: "string", required: false },
      country: { type: "string", required: false },
    },
  },
  plugins: [expo(), openAPI(), adminPlugin({ defaultRole: "homeowner" }), twoFactor()],
  emailAndPassword: {
    enabled: true,
    requireEmailVerification: true,
    sendResetPassword: async ({ user, url }, _request) => {
      await sendEmail({
        to: user.email,
        subject: "Reset your password",
        text: `Click the link to reset your password: ${url}`,
      });
    },
  },
  emailVerification: {
    sendOnSignUp: true,
    autoSignInAfterVerification: true,
    sendVerificationEmail: async ({ user, url }, _request) => {
      await sendEmail({
        to: user.email,
        subject: "Verify your email address",
        text: `Click the link to verify your email: ${url}`,
      });
      logger.info(`${user.email} verification email sent`, { id: user.id });
    },
  },
  trustedOrigins: [process.env.CORS_ORIGIN || "", "mybettertapp://", "exp://"],
  advanced: {
    defaultCookieAttributes: {
      sameSite: "none",
      secure: true,
      httpOnly: true,
    },
    database: {
      generateId: false,
    },
  },
} satisfies BetterAuthOptions;

export const auth = betterAuth(authOptions);
@imornar commented on GitHub (Oct 14, 2025): Checked, data exists correctly in database, when using just filters, it works as expected, when using just searches, it work as expected, when I combine both, always empty array. I'm using postgress with drizzle ``` import { drizzle } from "drizzle-orm/node-postgres"; import { schema } from "./schema"; export const db = drizzle({ connection: process.env.DATABASE_URL || "", casing: "snake_case", schema, }); ``` with auth config ``` export const drizzleAdapterOptions: DrizzleAdapterConfig = { provider: "pg", schema: authSchema, usePlural: true, }; export const authOptions = { appName: "AppName", database: drizzleAdapter(db, drizzleAdapterOptions), user: { additionalFields: { active: { type: "boolean", defaultValue: true }, about: { type: "string", required: false }, firstName: { type: "string", required: true, input: true }, lastName: { type: "string", required: true }, phone: { type: "string", required: true }, addressLine1: { type: "string", required: false }, addressLine2: { type: "string", required: false }, city: { type: "string", required: false }, state: { type: "string", required: false }, zipCode: { type: "string", required: false }, country: { type: "string", required: false }, }, }, plugins: [expo(), openAPI(), adminPlugin({ defaultRole: "homeowner" }), twoFactor()], emailAndPassword: { enabled: true, requireEmailVerification: true, sendResetPassword: async ({ user, url }, _request) => { await sendEmail({ to: user.email, subject: "Reset your password", text: `Click the link to reset your password: ${url}`, }); }, }, emailVerification: { sendOnSignUp: true, autoSignInAfterVerification: true, sendVerificationEmail: async ({ user, url }, _request) => { await sendEmail({ to: user.email, subject: "Verify your email address", text: `Click the link to verify your email: ${url}`, }); logger.info(`${user.email} verification email sent`, { id: user.id }); }, }, trustedOrigins: [process.env.CORS_ORIGIN || "", "mybettertapp://", "exp://"], advanced: { defaultCookieAttributes: { sameSite: "none", secure: true, httpOnly: true, }, database: { generateId: false, }, }, } satisfies BetterAuthOptions; export const auth = betterAuth(authOptions); ```
Author
Owner

@Kinfe123 commented on GitHub (Oct 14, 2025):

can you check on installing this - npm i https://pkg.pr.new/better-auth/better-auth@5311

@Kinfe123 commented on GitHub (Oct 14, 2025): can you check on installing this - `npm i https://pkg.pr.new/better-auth/better-auth@5311`
Author
Owner

@imornar commented on GitHub (Oct 15, 2025):

@Kinfe123 Perfect, that build you provided works correctly 🎊
Can you perhaps tell me more about when this issue might be hotfixed?

Thank you for picking this up so quickly — I’m honestly amazed by the responsiveness! It’s been greatly appreciated. 🙌

@imornar commented on GitHub (Oct 15, 2025): @Kinfe123 Perfect, that build you provided works correctly 🎊 Can you perhaps tell me more about when this issue might be hotfixed? Thank you for picking this up so quickly — I’m honestly amazed by the responsiveness! It’s been greatly appreciated. 🙌
Author
Owner

@Kinfe123 commented on GitHub (Oct 15, 2025):

Ref for pr - #5311

@Kinfe123 commented on GitHub (Oct 15, 2025): Ref for pr - #5311
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#2121