Free tool · Auth.js v5 · Next.js

Paste the Auth.js error.
Get the fix.

15 errors that break sign-in on Next.js, mostly right after you deploy. Each one comes with what it means, the fix and a prompt you can hand to Cursor or Claude Code.

auth-error-fixer — runs in your browser, nothing is sent

try:

› 15 errors indexed. Matching runs locally as you type.

  • 15 errors
  • 5 only show up in production
  • checked against next-auth 5.0.0-beta.32 · @auth/core 0.41.3 · Next.js 16.4.3
  • updated

01Works locally, breaks in prod

Your laptop is forgiving. Production isn't.

In development Auth.js trusts any host, reads secrets from .env.local and talks to the GitHub app you made for localhost. After you deploy, none of that holds. These are the 5 errors that only appear there:

  1. 01MissingSecretAUTH_SECRET is in .env.local but not in your host's environment variablesFix: set AUTH_SECRET on the host, redeploy →
  2. 02UntrustedHostRunning next start, Docker, Railway, Fly, Render or a VPS behind a proxyFix: trustHost: true or AUTH_TRUST_HOST=true →
  3. 03GitHub: redirect_uri mismatchSigning in on production with the localhost OAuth app's client IDFix: a second GitHub OAuth app for prod →
  4. 04Redirected to localhost after deployNEXTAUTH_URL=http://localhost:3000 copied from a v4 tutorial into the host's env varsFix: delete AUTH_URL / NEXTAUTH_URL in prod →
  5. 05AdapterError / table does not existMigrations never ran against the production databaseFix: npx prisma migrate deploy on Postgres →
  6. pre-deploy check
    • AUTH_SECRET set on the host
    • trustHost: true (if not on Vercel)
    • Production GitHub OAuth app
    • No localhost AUTH_URL
    • Migrations run on prod DB

02Every error, explained

The full list.

01browser URL

error=Configuration

/api/auth/error?error=Configuration

This is a cover, not the real error. Auth.js only sends a few error types to the browser (AccessDenied, Verification, OAuthAccountNotLinked and a handful more). Everything else, like a missing secret or a database failure, shows up as Configuration so it can't leak details.

usually because

  • The real error is in your server logs, on a line starting with [auth][error]
  • Most often MissingSecret, UntrustedHost or an AdapterError

works with next-auth 5.0.0-beta.32 · @auth/core 0.41.3 · Next.js 16.4.3last verified

fix

  1. 1.Open the logs where the app runs (Vercel → Deployments → Logs, or your terminal)
  2. 2.Find the [auth][error] line and paste it into the box above
  3. 3.Add debug: true to your NextAuth config temporarily if the line isn't there
prompt for your agent

Sign-in redirects to /api/auth/error?error=Configuration. Don't guess. Tell me where my server logs are for this host, then read the [auth][error] line and fix only that root cause.

02server logprod only

MissingSecret

[auth][error] MissingSecret: Please define a `secret`. Read more at https://errors.authjs.dev#missingsecret

Auth.js has no secret to encrypt cookies and tokens with. It reads AUTH_SECRET (or AUTH_SECRET_1, _2, _3 for rotation). next-auth v5 still falls back to the old NEXTAUTH_SECRET.

usually because

  • AUTH_SECRET is in .env.local but not in your host's environment variables
  • The variable was added after the last deploy, so the running build doesn't see it
  • A typo like AUTH_SECRETS or NEXT_PUBLIC_AUTH_SECRET

works with next-auth 5.0.0-beta.32 · @auth/core 0.41.3 · Next.js 16.4.3last verified

fix

  1. 1.Generate one: npx auth secret (or openssl rand -base64 33)
  2. 2.Add AUTH_SECRET to the production environment on your host
  3. 3.Redeploy so the new value is picked up
  4. 4.Never prefix it with NEXT_PUBLIC_: that ships it to the browser
.env.local
# at least 32 random characters
AUTH_SECRET="paste-the-output-of-npx-auth-secret"
prompt for your agent

Auth.js throws MissingSecret in production. Check which env vars my auth.ts reads, confirm AUTH_SECRET is set for the production environment on my host (not only in .env.local), and make sure it is never exposed with a NEXT_PUBLIC_ prefix.

03server logprod only

UntrustedHost

[auth][error] UntrustedHost: Host must be trusted. URL was: https://your-app.com/api/auth/session. Read more at https://errors.authjs.dev#untrustedhost

Auth.js builds callback URLs from the request's Host header and refuses to trust it by default in production. In development (NODE_ENV not production) it trusts the host automatically, which is why this only appears after you deploy.

usually because

  • Running next start, Docker, Railway, Fly, Render or a VPS behind a proxy
  • Vercel and Cloudflare Pages are detected automatically (VERCEL / CF_PAGES env vars), most other hosts are not

works with next-auth 5.0.0-beta.32 · @auth/core 0.41.3 · Next.js 16.4.3last verified

fix

  1. 1.Set trustHost: true in your NextAuth config, or
  2. 2.Set AUTH_TRUST_HOST=true in the production environment
  3. 3.Setting AUTH_URL also counts as trusting the host
src/auth.ts
export const { handlers, auth, signIn, signOut } = NextAuth({
  trustHost: true, // needed for next start, Docker and most non-Vercel hosts
  providers: [GitHub],
});
prompt for your agent

Auth.js logs UntrustedHost after deploying with next start. Add trustHost: true to the NextAuth config in auth.ts (or tell me to set AUTH_TRUST_HOST=true on the host) and explain why it worked locally.

04GitHub pageprod only

GitHub: redirect_uri mismatch

error=redirect_uri_mismatch · The redirect_uri is not associated with this application.

The callback URL Auth.js sent to GitHub doesn't match the one registered on your GitHub OAuth app. A GitHub OAuth app has one callback URL, so the app you made for localhost can't also serve production.

usually because

  • Signing in on production with the localhost OAuth app's client ID
  • http vs https, www vs no www, or a different port
  • A preview deployment URL that changes on every deploy

works with next-auth 5.0.0-beta.32 · @auth/core 0.41.3 · Next.js 16.4.3last verified

fix

  1. 1.Create a second GitHub OAuth app for production (github.com/settings/developers)
  2. 2.Set its callback URL to https://your-domain.com/api/auth/callback/github
  3. 3.Put that app's ID and secret in production as AUTH_GITHUB_ID and AUTH_GITHUB_SECRET
  4. 4.For previews, Auth.js supports a stable redirect proxy via AUTH_REDIRECT_PROXY_URL
GitHub OAuth app (production)
Homepage URL:   https://your-domain.com
Callback URL:   https://your-domain.com/api/auth/callback/github
prompt for your agent

GitHub sign-in fails in production with redirect_uri_mismatch. List the exact callback URL my app sends (base path /api/auth, provider github) for my production domain, and the env vars I need for a separate production GitHub OAuth app.

05browser URLprod only

Redirected to localhost after deploy

https://your-app.com → sign in → http://localhost:3000/api/auth/callback/github

If AUTH_URL or NEXTAUTH_URL is set, next-auth v5 rewrites the request's origin to it. A localhost value copied into production sends every user back to localhost.

usually because

  • NEXTAUTH_URL=http://localhost:3000 copied from a v4 tutorial into the host's env vars
  • AUTH_URL left over from local testing

works with next-auth 5.0.0-beta.32 · @auth/core 0.41.3 · Next.js 16.4.3last verified

fix

  1. 1.Delete AUTH_URL and NEXTAUTH_URL from production. v5 infers the host from the request
  2. 2.Only set AUTH_URL when Auth.js lives under a different base path
  3. 3.Redeploy
prompt for your agent

After deploying, sign-in sends users to localhost. Find every place AUTH_URL or NEXTAUTH_URL is set or read, and tell me which ones to remove for production on Auth.js v5.

06browser URL

OAuthAccountNotLinked

/login?error=OAuthAccountNotLinked

Someone already has an account with this email, created with a different sign-in method (say, a magic link), and now tries GitHub. For security, Auth.js won't attach the new provider to an existing user who isn't signed in.

usually because

  • Same email used with email magic link first, GitHub second (or the reverse)
  • Test users left in your dev database

works with next-auth 5.0.0-beta.32 · @auth/core 0.41.3 · Next.js 16.4.3last verified

fix

  1. 1.Show a friendly message on your sign-in page: "Sign in the way you did the first time"
  2. 2.Let signed-in users link extra providers from their account page
  3. 3.allowDangerousEmailAccountLinking: true on a provider turns on auto-linking. Only use it if you trust that provider to verify emails
src/app/login/page.tsx
const messages: Record<string, string> = {
  OAuthAccountNotLinked: "That email already has an account. Sign in the way you did the first time.",
  Verification: "That sign-in link expired or was already used. Request a new one.",
};
prompt for your agent

Users who signed up with a magic link get OAuthAccountNotLinked when they try GitHub. Show a clear message for ?error=OAuthAccountNotLinked on my sign-in page. Don't enable allowDangerousEmailAccountLinking unless I confirm.

07browser URL

error=Verification

/api/auth/error?error=Verification

The magic-link token wasn't found or has expired. Each link works once, and the email provider's default lifetime is 24 hours.

usually because

  • The link was clicked twice, or a newer link replaced it
  • The link is older than 24 hours
  • The verification token was written to a different database than the one the app reads now

works with next-auth 5.0.0-beta.32 · @auth/core 0.41.3 · Next.js 16.4.3last verified

fix

  1. 1.Ask the user to request a new link, and say so on the error page
  2. 2.Make sure dev and prod don't share or swap DATABASE_URL
  3. 3.Raise maxAge on the email provider only if you have a reason to
prompt for your agent

Magic-link sign-in lands on error=Verification. Check my email provider config, the VerificationToken table and DATABASE_URL per environment, and add a 'request a new link' message for this error.

08server log

MissingAdapter

[auth][error] MissingAdapter: Email login requires an adapter. Read more at https://errors.authjs.dev#missingadapter

Magic links (Email / Nodemailer / Resend providers) and session: { strategy: "database" } both need a database adapter to store tokens and sessions.

usually because

  • Added the Nodemailer or Resend provider without an adapter
  • Set strategy: "database" without an adapter
  • Imported the adapter but passed it in only one of two config files

works with next-auth 5.0.0-beta.32 · @auth/core 0.41.3 · Next.js 16.4.3last verified

fix

  1. 1.Install @auth/prisma-adapter (v5 adapters live under @auth/, not @next-auth/)
  2. 2.Pass adapter: PrismaAdapter(db) to NextAuth
  3. 3.Add the User, Account, Session and VerificationToken models and run a migration
src/auth.ts
import { PrismaAdapter } from "@auth/prisma-adapter";
import { db } from "@/lib/db";

export const { handlers, auth, signIn, signOut } = NextAuth({
  adapter: PrismaAdapter(db),
  session: { strategy: "database" },
  providers,
});
prompt for your agent

Auth.js says MissingAdapter. Wire @auth/prisma-adapter into auth.ts, check my Prisma schema has the User, Account, Session and VerificationToken models from the Auth.js Prisma adapter docs, and give me the migration command.

09server logprod only

AdapterError / table does not exist

[auth][error] AdapterError … The table `main.User` does not exist in the current database.

One of the adapter's database calls failed. The cause line under it says why, and with Prisma it's usually a missing table or an unreachable database.

usually because

  • Migrations never ran against the production database
  • DATABASE_URL points to SQLite on a serverless host, where the file doesn't persist
  • Schema models renamed so they no longer match what the adapter expects

works with next-auth 5.0.0-beta.32 · @auth/core 0.41.3 · Next.js 16.4.3last verified

fix

  1. 1.Run npx prisma migrate deploy against production (or prisma db push while prototyping)
  2. 2.Use Postgres in production. SQLite files don't survive serverless deploys
  3. 3.Set debug: true once to see which adapter_ method failed
prompt for your agent

Auth.js logs AdapterError with a Prisma 'table does not exist' cause in production. Check DATABASE_URL and the Prisma provider for prod, then give me the exact migrate command to run and where to run it.

10server log

InvalidCheck (PKCE / state)

[auth][error] InvalidCheck: pkceCodeVerifier value could not be parsed. Read more at https://errors.authjs.dev#invalidcheck

Auth.js sets a short-lived cookie when sign-in starts and checks it when the provider sends the user back. The cookie was missing on the way back.

usually because

  • Starting on 127.0.0.1 and coming back to localhost (or www vs no www): different cookie jars
  • The callback lands on a different domain than the one sign-in started on
  • Cookies blocked in the browser, or a custom cookies config

works with next-auth 5.0.0-beta.32 · @auth/core 0.41.3 · Next.js 16.4.3last verified

fix

  1. 1.Use one exact origin everywhere: the address bar, the OAuth app and any AUTH_URL
  2. 2.Redirect www to the apex domain (or the reverse) at the host
  3. 3.Remove custom cookies options unless you need them
prompt for your agent

GitHub sign-in fails with InvalidCheck (pkceCodeVerifier). Check whether sign-in starts and returns on the same origin (localhost vs 127.0.0.1, www vs apex), and whether my config overrides cookies.

11server log

JWTSessionError

[auth][error] JWTSessionError: Read more at https://errors.authjs.dev#jwtsessionerror  [auth][cause]: Error: no matching decryption secret

With strategy "jwt", Auth.js couldn't decrypt the session cookie. The cookie was encrypted with a different secret, so it's destroyed and the user is signed out.

usually because

  • AUTH_SECRET changed (or differs between preview and production)
  • An old cookie from another app on localhost:3000

works with next-auth 5.0.0-beta.32 · @auth/core 0.41.3 · Next.js 16.4.3last verified

fix

  1. 1.For one user: clear cookies for the site and sign in again
  2. 2.To rotate without signing everyone out, set the new secret as AUTH_SECRET and keep the old one as AUTH_SECRET_1 for a while
  3. 3.Use the same secret on every deployment that shares the domain
prompt for your agent

Auth.js logs JWTSessionError: no matching decryption secret. Check whether AUTH_SECRET differs between environments and set up AUTH_SECRET_1 rotation if I changed it on purpose.

12server log

SessionTokenError

[auth][error] SessionTokenError: Read more at https://errors.authjs.dev#sessiontokenerror

With strategy "database", Auth.js couldn't read the session from the database. The adapter is misconfigured or the database can't be reached.

usually because

  • Database down or DATABASE_URL wrong in this environment
  • Connection limit hit on serverless Postgres without pooling

works with next-auth 5.0.0-beta.32 · @auth/core 0.41.3 · Next.js 16.4.3last verified

fix

  1. 1.Check the cause line and your database dashboard
  2. 2.Use your provider's pooled connection string on serverless
  3. 3.Reuse one Prisma client (a global singleton in dev)
prompt for your agent

Auth.js logs SessionTokenError with database sessions. Check DATABASE_URL for this environment, whether I use a pooled connection on serverless, and that my Prisma client is a singleton.

13browser URL

AccessDenied

/api/auth/error?error=AccessDenied

Your signIn callback returned false (or threw), or the user clicked Cancel on the provider's consent screen.

usually because

  • An allow-list in callbacks.signIn that doesn't include this email
  • The user declined on GitHub

works with next-auth 5.0.0-beta.32 · @auth/core 0.41.3 · Next.js 16.4.3last verified

fix

  1. 1.Log the inputs in callbacks.signIn to see why it returned false
  2. 2.Return a redirect path string from signIn instead of false to send blocked users somewhere useful
prompt for your agent

Sign-in ends at error=AccessDenied. Show me my callbacks.signIn logic, log why it returns false for this user, and suggest returning a friendly redirect instead.

14server log

MissingCSRF

[auth][error] MissingCSRF: CSRF token was missing during an action signin. Read more at https://errors.authjs.dev#missingcsrf

A sign-in or sign-out POST arrived without Auth.js's CSRF cookie and token. Often it's a hand-rolled fetch to /api/auth/signin instead of the provided helpers.

usually because

  • fetch('/api/auth/signin/…', { method: 'POST' }) written by hand
  • A form posting to the Auth.js endpoint from another origin

works with next-auth 5.0.0-beta.32 · @auth/core 0.41.3 · Next.js 16.4.3last verified

fix

  1. 1.Use signIn() from your auth.ts in a Server Action, or signIn from next-auth/react in a Client Component
  2. 2.Don't call the /api/auth endpoints directly
src/app/login/page.tsx
import { signIn } from "@/auth";

<form action={async () => { "use server"; await signIn("github", { redirectTo: "/dashboard" }); }}>
  <button>Sign in with GitHub</button>
</form>
prompt for your agent

Auth.js logs MissingCSRF. Find any hand-written fetch or form that posts to /api/auth/* and replace it with signIn() from auth.ts in a Server Action.

15build / TypeScript

v4 code in a v5 app (getServerSession, authOptions)

Module '"next-auth"' has no exported member 'NextAuthOptions'. · getServerSession(authOptions)

Your AI agent wrote NextAuth v4 code. A lot of tutorials and training data are from v4, so agents mix the two APIs unless you tell them which version you use.

usually because

  • getServerSession(authOptions) and next-auth/next imports
  • NextAuthOptions (renamed NextAuthConfig)
  • export { default } from "next-auth/middleware"
  • @next-auth/prisma-adapter (now @auth/prisma-adapter)

works with next-auth 5.0.0-beta.32 · @auth/core 0.41.3 · Next.js 16.4.3last verified

prevent it · 00-workflow.mdc (free Cursor Rules Pack): Makes the agent check the installed next-auth version in package.json before writing auth code, so v4 examples don't land in a v5 app.

fix

  1. 1.Call auth() from your auth.ts everywhere on the server
  2. 2.Export auth as proxy in proxy.ts (Next.js 16 renamed middleware.ts)
  3. 3.Add a rule telling your agent the project uses Auth.js v5 and to check package.json before writing auth code
src/app/dashboard/page.tsx
- import { getServerSession } from "next-auth/next"
- const session = await getServerSession(authOptions)
+ import { auth } from "@/auth"
+ const session = await auth()
prompt for your agent

This project uses Auth.js v5 (next-auth@5). Search for getServerSession, authOptions, NextAuthOptions, next-auth/next, next-auth/middleware, getToken and @next-auth/ imports and migrate each one to the v5 auth() API. List every file you change.

03Or skip the debugging

Start from an Auth.js v5 setup that already deploys.

Skip the setup. The VibeBoot SaaS Starter ships Auth.js v5 already wired (GitHub sign-in, optional email magic links, Prisma adapter), plus Stripe and a database on Next.js 16.4.3. $49, one-time.

14-day money-back guarantee · lifetime updates

See everything that's inside →
  • trustHost: true · already set in auth.ts, so next start and Docker don't throw UntrustedHost
  • AUTH_SECRET · documented in .env.example with the npx auth secret command
  • Production GitHub app · README and launch checklist walk through the second OAuth app and its callback URL
  • Magic links optional · the email provider only turns on when EMAIL_SERVER is set, so builds don't need SMTP
  • v5 only · AGENTS.md, CLAUDE.md and .cursor/rules tell your agent to use auth(), not v4 APIs
  • Prisma adapter · database sessions with SQLite by default; Postgres by changing the provider and DATABASE_URL

FAQ

Why does Auth.js work locally but fail after I deploy?

Three defaults change in production. Auth.js trusts the Host header automatically only when NODE_ENV isn't production, so UntrustedHost appears on next start, Docker and most non-Vercel hosts. AUTH_SECRET is often only in .env.local, which your host never sees. And a GitHub OAuth app has a single callback URL, so the localhost app can't serve your real domain.

What does error=Configuration mean in NextAuth v5?

It's a generic error page. Auth.js only sends a few error types to the browser (such as AccessDenied, Verification and OAuthAccountNotLinked), and shows everything else as Configuration so server details don't leak. The real error is on the [auth][error] line in your server logs.

Do I still need NEXTAUTH_URL and NEXTAUTH_SECRET in v5?

No. v5 uses the AUTH_ prefix and infers the URL from the request. next-auth v5 still reads NEXTAUTH_SECRET as a fallback, but a leftover NEXTAUTH_URL or AUTH_URL pointing at localhost will redirect production users to localhost, so remove it unless you use a custom base path.

Is anything I paste sent to a server?

No. The matcher is plain JavaScript in this page. Nothing you paste is stored or sent anywhere, but it's still good practice to strip secrets and emails from logs before sharing them.

Which Auth.js version is this for?

Auth.js v5 for Next.js (the next-auth@beta package), checked against next-auth 5.0.0-beta.32 · @auth/core 0.41.3 · Next.js 16.4.3 and the Auth.js docs on October 27, 2026. Most entries also apply to other Auth.js frameworks, but their default base path is /auth instead of /api/auth.

Sources: the Auth.js errors reference, deployment guide and v5 migration guide, the next-auth 5.0.0-beta.32 · @auth/core 0.41.3 · Next.js 16.4.3 source, and GitHub's OAuth troubleshooting docs. Checked October 27, 2026. Spotted a mistake? Email [email protected].

More free tools: Cursor Rules Pack · AGENTS.md generator · newsletter

$ fixed it? get the next one first

New fixes for what AI agents break, by email.

When we add a fix or a Cursor rule for a new Next.js, Auth.js, Prisma or Stripe break, it goes out in the VibeBoot newsletter. Free, occasional, unsubscribe in one click.

Subscribe free

> More free tools

All tools →