"[object Object]" is not valid JSON

i am using nextjs 15.3.1 app router with typescript, betterauth 1.2.7.
import { auth } from "@/lib/auth";
import { headers } from "next/headers";
export default async function Home() {
const session = await auth.api.getSession({
headers: await headers(),
});
console.log({ session });
// rest of the page code
}
import { auth } from "@/lib/auth";
import { headers } from "next/headers";
export default async function Home() {
const session = await auth.api.getSession({
headers: await headers(),
});
console.log({ session });
// rest of the page code
}
Why am i getting SyntaxError: "[object Object]" is not valid JSON in log? Also, getting the same error in this log on the server (in browser console it gives error FAILED_TO_GET_SESSION)
"use client";
import { authClient } from "@/lib/auth/auth-client";
export default function UserBtn() {
const data = authClient.useSession();
console.log(data);
// rest of the component code
}
"use client";
import { authClient } from "@/lib/auth/auth-client";
export default function UserBtn() {
const data = authClient.useSession();
console.log(data);
// rest of the component code
}
i am following betterauth docs exactly. is there any error in nextjs or better auth or my code?
4 Replies
KiNFiSH
KiNFiSH2w ago
Can you share you Auth config ?
Shezan
ShezanOP7d ago
// @/lib/auth/index.ts
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { db } from "@/lib/db";
import { redis } from "../rateLimiter";
import { sendPassResetMail, sendVerificationMail } from "../email/auth-mails";
import { pageLinks } from "../constants/links";
import { nextCookies } from "better-auth/next-js";

export const auth = betterAuth({
basePath: "http://localhost:3000/",
database: drizzleAdapter(db, { provider: "pg" }),
secondaryStorage: {
get: async (key) => await redis.get(key),
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);
},
prefix: "auth-ratelimit",
},
rateLimit: {
window: 60,
max: 6,
customRules: {
"/sign-in/email": { window: 3600, max: 6 },
},
storage: "secondary-storage",
},
emailAndPassword: {
enabled: true,
minPasswordLength: 6,
maxPasswordLength: 64,
autoSignIn: false,
requireEmailVerification: true,
sendResetPassword: async ({ user, url }) =>
await sendPassResetMail({ email: user.email, url }),
},
account: { accountLinking: { enabled: true, trustedProviders: ["google"] } },
socialProviders: {
google: {
prompt: "select_account",
clientId: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
},
},
emailVerification: {
sendVerificationEmail: async ({ user, url }) => {
const link = `${url}?callback=${pageLinks.onSignIn}`;
return await sendVerificationMail({ email: user.email, url: link });
},
autoSignInAfterVerification: true,
sendOnSignUp: true,
},
plugins: [nextCookies()],
});
// @/lib/auth/index.ts
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { db } from "@/lib/db";
import { redis } from "../rateLimiter";
import { sendPassResetMail, sendVerificationMail } from "../email/auth-mails";
import { pageLinks } from "../constants/links";
import { nextCookies } from "better-auth/next-js";

export const auth = betterAuth({
basePath: "http://localhost:3000/",
database: drizzleAdapter(db, { provider: "pg" }),
secondaryStorage: {
get: async (key) => await redis.get(key),
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);
},
prefix: "auth-ratelimit",
},
rateLimit: {
window: 60,
max: 6,
customRules: {
"/sign-in/email": { window: 3600, max: 6 },
},
storage: "secondary-storage",
},
emailAndPassword: {
enabled: true,
minPasswordLength: 6,
maxPasswordLength: 64,
autoSignIn: false,
requireEmailVerification: true,
sendResetPassword: async ({ user, url }) =>
await sendPassResetMail({ email: user.email, url }),
},
account: { accountLinking: { enabled: true, trustedProviders: ["google"] } },
socialProviders: {
google: {
prompt: "select_account",
clientId: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
},
},
emailVerification: {
sendVerificationEmail: async ({ user, url }) => {
const link = `${url}?callback=${pageLinks.onSignIn}`;
return await sendVerificationMail({ email: user.email, url: link });
},
autoSignInAfterVerification: true,
sendOnSignUp: true,
},
plugins: [nextCookies()],
});
And here's the authClient
// @/lib/auth/auth-client.ts
import { createAuthClient } from "better-auth/react";
import { toast } from "sonner";
export const authClient = createAuthClient({
fetchOptions: {
onError: async (ctx) => {
const { response } = ctx;
if (response.status === 429) {
const retryAfter = response.headers.get("X-Retry-After");
toast.error(`Rate limit exceeded. Retry after ${retryAfter} seconds`);
}
},
},
});
// @/lib/auth/auth-client.ts
import { createAuthClient } from "better-auth/react";
import { toast } from "sonner";
export const authClient = createAuthClient({
fetchOptions: {
onError: async (ctx) => {
const { response } = ctx;
if (response.status === 429) {
const retryAfter = response.headers.get("X-Retry-After");
toast.error(`Rate limit exceeded. Retry after ${retryAfter} seconds`);
}
},
},
});
KiNFiSH
KiNFiSH7d ago
may be it might be on the secondary storage ? can you try out with that just to make sure
Shezan
ShezanOP6d ago
yes. commenting out the second storage worked. But why? how would i implement rateLimit then? Is there a way to only use secondaryStorage only for rate limiting?

Did you find this page helpful?