Issue for secondaryStorage with redis #764

Closed
opened 2026-03-13 08:03:23 -05:00 by GiteaMirror · 4 comments
Owner

Originally created by @akawahuynh on GitHub (Mar 2, 2025).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Create connect redis

  2. Login first

Image

  1. Log out

Image

  1. Login Second

Image

Current vs. Expected behavior

SERVER_ERROR: [TypeError: list.filter is not a function]

if not using secondaryStorage + reddit: login second was successful

I think the reason for the error is that

delete: async (key) => {
console.log("DELETE:", key);
await redis.del(key);
},

does not delete the active-sessions-* key

What version of Better Auth are you using?

1.2.0

Provide environment information

- OS: Windows 11
- Browser: Chrome

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

Backend

Auth config (if applicable)

import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { db } from "@/db";
import * as schema from "@/db/schema";
import { nextCookies } from "better-auth/next-js";
import { admin, openAPI } from "better-auth/plugins";
import sendEmail from "./resend";
import { createAuthMiddleware, APIError } from "better-auth/api";
import redis from "./redisClient";

export const auth = betterAuth({
  baseURL: process.env.BETTER_AUTH_URL,
  database: drizzleAdapter(db, {
    provider: "pg",
    schema: {
      ...schema,
      user: schema.users,
    },
    usePlural: true,
  }),
  emailAndPassword: {
    enabled: true,
    requireEmailVerification: true,
    resetPasswordTokenExpiresIn: 5 * 60,
    sendResetPassword: async ({ user, url }) => {
      await sendEmail({
        to: user.email,
        subject: "Reset your password",
        html: `Click the link to reset your password: <a href="${url}">${url}</a>`,
        text: `Click the link to reset your password: ${url}`,
      });
    },
  },
  session: {
    cookieCache: {
      enabled: true,
      maxAge: 5 * 60,
    },
  },
  plugins: [
    nextCookies(),
    admin({
      defaultBanReason: "Spamming",
    }),
    openAPI({
      disableDefaultReference: process.env.NODE_ENV === "production",
    }),
  ],
  emailVerification: {
    sendVerificationEmail: async ({ user, url }) => {
      await sendEmail({
        to: user.email,
        subject: "Verify your email address",
        html: `Click the link to verify your email: <a href="${url}">${url}</a>`,
        text: `Click the link to verify your email: ${url}`,
      });
    },
  },

  secondaryStorage: {
    get: async (key) => {
      const value = await redis.get(key);
      console.log("GET :", key);
      console.log("GET value :", value);
      return value ? JSON.stringify(value) : null;
    },
    set: async (key, value, ttl) => {
      console.log("SET key:", key);
      console.log("SET value:", value);
      console.log("SET TTL:", ttl);

      if (ttl) await redis.set(key, value, "EX", ttl);
      else await redis.set(key, value);
    },
    delete: async (key) => {
      console.log("DELETE:", key);
      await redis.del(key);
    },
  },
  hooks: {
    before: createAuthMiddleware(async (ctx) => {
      if (
        ctx.path === "/sign-up/email" &&
        ctx.body?.email.endsWith("@example.com")
      ) {
        throw new APIError("BAD_REQUEST", {
          message: "Email must end with @example.com",
        });
      }
      if (
        ctx.path === "/sign-in/email" &&
        !ctx.body?.email.endsWith("@example.com")
      ) {
      }
    }),
  },
});

Additional context

No response

Originally created by @akawahuynh on GitHub (Mar 2, 2025). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1. Create connect redis 2. Login first ![Image](https://github.com/user-attachments/assets/a5e8d710-3008-435b-9e0c-0cbf334f8f03) 3. Log out ![Image](https://github.com/user-attachments/assets/1b008cce-0016-466e-96fc-add165c6fc62) 4. Login Second ![Image](https://github.com/user-attachments/assets/cf38424d-10c5-415f-b96c-8bdf6a8c1d05) ### Current vs. Expected behavior # SERVER_ERROR: [TypeError: list.filter is not a function] if not using secondaryStorage + reddit: login second was successful I think the reason for the error is that ``` delete: async (key) => { console.log("DELETE:", key); await redis.del(key); }, ``` does not delete the active-sessions-* key ### What version of Better Auth are you using? 1.2.0 ### Provide environment information ```bash - OS: Windows 11 - Browser: Chrome ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth"; import { drizzleAdapter } from "better-auth/adapters/drizzle"; import { db } from "@/db"; import * as schema from "@/db/schema"; import { nextCookies } from "better-auth/next-js"; import { admin, openAPI } from "better-auth/plugins"; import sendEmail from "./resend"; import { createAuthMiddleware, APIError } from "better-auth/api"; import redis from "./redisClient"; export const auth = betterAuth({ baseURL: process.env.BETTER_AUTH_URL, database: drizzleAdapter(db, { provider: "pg", schema: { ...schema, user: schema.users, }, usePlural: true, }), emailAndPassword: { enabled: true, requireEmailVerification: true, resetPasswordTokenExpiresIn: 5 * 60, sendResetPassword: async ({ user, url }) => { await sendEmail({ to: user.email, subject: "Reset your password", html: `Click the link to reset your password: <a href="${url}">${url}</a>`, text: `Click the link to reset your password: ${url}`, }); }, }, session: { cookieCache: { enabled: true, maxAge: 5 * 60, }, }, plugins: [ nextCookies(), admin({ defaultBanReason: "Spamming", }), openAPI({ disableDefaultReference: process.env.NODE_ENV === "production", }), ], emailVerification: { sendVerificationEmail: async ({ user, url }) => { await sendEmail({ to: user.email, subject: "Verify your email address", html: `Click the link to verify your email: <a href="${url}">${url}</a>`, text: `Click the link to verify your email: ${url}`, }); }, }, secondaryStorage: { get: async (key) => { const value = await redis.get(key); console.log("GET :", key); console.log("GET value :", value); return value ? JSON.stringify(value) : null; }, set: async (key, value, ttl) => { console.log("SET key:", key); console.log("SET value:", value); console.log("SET TTL:", ttl); if (ttl) await redis.set(key, value, "EX", ttl); else await redis.set(key, value); }, delete: async (key) => { console.log("DELETE:", key); await redis.del(key); }, }, hooks: { before: createAuthMiddleware(async (ctx) => { if ( ctx.path === "/sign-up/email" && ctx.body?.email.endsWith("@example.com") ) { throw new APIError("BAD_REQUEST", { message: "Email must end with @example.com", }); } if ( ctx.path === "/sign-in/email" && !ctx.body?.email.endsWith("@example.com") ) { } }), }, }); ``` ### Additional context _No response_
GiteaMirror added the bug label 2026-03-13 08:03:23 -05:00
Author
Owner

@x751685875 commented on GitHub (Mar 5, 2025):

I also encountered this problem.

@x751685875 commented on GitHub (Mar 5, 2025): I also encountered this problem.
Author
Owner

@kadumedim commented on GitHub (Mar 12, 2025):

Still happening on 1.2.3

@kadumedim commented on GitHub (Mar 12, 2025): Still happening on 1.2.3
Author
Owner

@desenvolvimento02jocc commented on GitHub (Mar 12, 2025):

+1, I don't know how can I use a fast access kv db without this being fixed

@desenvolvimento02jocc commented on GitHub (Mar 12, 2025): +1, I don't know how can I use a fast access kv db without this being fixed
Author
Owner

@SpatzlHD commented on GitHub (Mar 12, 2025):

I did encounter the same error yesterday but managed to fix it by removing the JSON.stringify function in the get call. Here is my implementation of the secondaryStrorage methode using ioredis:

secondaryStorage: {
    get: async (key) => {
      const value = await redis.get(key);
      return value ? value : null;
    },
    set: async (key, value, ttl) => {
      if (ttl) {
        await redis.set(key, value, "EX", ttl);
      } else {
        await redis.set(key, value);
      }
    },
    delete: async (key) => {
      await redis.del(key);
    },
  }
@SpatzlHD commented on GitHub (Mar 12, 2025): I did encounter the same error yesterday but managed to fix it by removing the `JSON.stringify` function in the get call. Here is my implementation of the secondaryStrorage methode using ioredis: ```js secondaryStorage: { get: async (key) => { const value = await redis.get(key); return value ? value : null; }, set: async (key, value, ttl) => { if (ttl) { await redis.set(key, value, "EX", ttl); } else { await redis.set(key, value); } }, delete: async (key) => { await redis.del(key); }, } ```
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#764