Better Auth Error Diagnostician & Explainer
This skill diagnoses and provides actionable resolutions for common Better Auth runtime errors, client error codes, configuration pitfalls, and database adapter issues.
Common Error Codes & Resolutions
1. INVALID_EMAIL_OR_PASSWORD
- Cause: User credentials do not match database records, or password hashing mismatch.
- Resolution:
- Verify that password hashing algorithm has not changed between migrations.
- Verify that input email is trimmed/lowercased if
emailAndPassword.autoSignInor normalization is enabled. - Check client-side error handling:
const { data, error } = await authClient.signIn.email({ email, password, }) if (error?.status === 401 || error?.code === 'INVALID_EMAIL_OR_PASSWORD') { // Prompt user with user-friendly message }
2. USER_ALREADY_EXISTS
- Cause: Attempting to sign up with an email or account ID already in use.
- Resolution:
- Direct user to sign in or password reset flow.
- If social login is used with existing email, check
accountLinking.enabled:export const auth = betterAuth({ account: { accountLinking: { enabled: true, trustedProviders: ['google', 'github'], }, }, })
3. SESSION_EXPIRED / UNAUTHORIZED
- Cause: Cookie expired, missing
credentials: "include"on cross-origin fetch, or cookie domain mismatch. - Resolution:
- Client side: ensure
authClienthas the exactbaseURLmatching server. - Cross-domain setup:
export const auth = betterAuth({ trustedOrigins: ['https://app.example.com', 'http://localhost:3000'], advanced: { crossSubDomainCookies: { enabled: true, domain: '.example.com', }, }, })
- Client side: ensure
4. FAILED_TO_VERIFY_EMAIL / INVALID_TOKEN
- Cause: Verification token expired or used already.
- Resolution:
- Verify email verification URL configuration in
emailVerification:emailVerification: { sendOnSignUp: true, autoSignInAfterVerification: true, sendVerificationEmail: async ({ user, url, token }) => { await sendEmail({ to: user.email, url }) }, }
- Verify email verification URL configuration in
5. ADAPTER_ERROR / Database Schema Mismatches
- Cause: Database tables do not match Better Auth expectations (missing columns like
emailVerified,image,twoFactorEnabled, or relation tables). - Resolution:
- Run the Better Auth CLI schema generator / migration tool:
npx @better-auth/cli generate npx @better-auth/cli migrate - If using Prisma, ensure schema has all required Better Auth models:
User,Session,Account,Verification.
- Run the Better Auth CLI schema generator / migration tool:
6. CORS / Preflight Failure on /api/auth/*
- Cause: Missing CORS headers or allowed methods on the API route handler.
- Resolution:
- In Next.js / Hono / Express, ensure
toNextJsHandleror framework adapter exposesGETandPOST. - Ensure
BETTER_AUTH_URLmatches the canonical deployment URL.
- In Next.js / Hono / Express, ensure
Diagnostic Checklist
When debugging an unknown Better Auth issue:
- Check server console logs with
logger: { level: "debug" }enabled inbetterAuth(). - Inspect network tab response payload for the
{ code, message }JSON object. - Verify database adapter connection string and table prefixes.
- Verify cookie configuration in production (
secure: truerequires HTTPS).