explain-error · v1.0.0 · 2026-09-03 · sha256 2fb12603f46df3a5
explain-error v1.0.0A
Immutable. This exact content is served forever at /api/v1/blob/2fb12603f46df3a5.
---
name: explain-error
description: Automatically diagnoses, explains, and resolves Better Auth runtime errors, configuration issues, database adapter mismatches, and authentication failure codes.
version: 1.0.0
---
# 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.autoSignIn` or normalization is enabled.
- Check client-side error handling:
```typescript
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`:
```typescript
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 `authClient` has the exact `baseURL` matching server.
- Cross-domain setup:
```typescript
export const auth = betterAuth({
trustedOrigins: ['https://app.example.com', 'http://localhost:3000'],
advanced: {
crossSubDomainCookies: {
enabled: true,
domain: '.example.com',
},
},
})
```
### 4. `FAILED_TO_VERIFY_EMAIL` / `INVALID_TOKEN`
- **Cause**: Verification token expired or used already.
- **Resolution**:
- Verify email verification URL configuration in `emailVerification`:
```typescript
emailVerification: {
sendOnSignUp: true,
autoSignInAfterVerification: true,
sendVerificationEmail: async ({ user, url, token }) => {
await sendEmail({ to: user.email, url })
},
}
```
### 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:
```bash
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`.
### 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 `toNextJsHandler` or framework adapter exposes `GET` and `POST`.
- Ensure `BETTER_AUTH_URL` matches the canonical deployment URL.
## Diagnostic Checklist
When debugging an unknown Better Auth issue:
1. Check server console logs with `logger: { level: "debug" }` enabled in `betterAuth()`.
2. Inspect network tab response payload for the `{ code, message }` JSON object.
3. Verify database adapter connection string and table prefixes.
4. Verify cookie configuration in production (`secure: true` requires HTTPS).