Deployment troubleshooting
The health check, the IPv6 database endpoint, db:push crashes and sign-in that only fails in production.
Everything here is about a Teleprompt instance you are hosting yourself: a deployment that will not sign anyone in, a database it cannot reach, a CLI that stops with a stack trace. The setup itself is on Running your own.
The health check
Start here, because Auth.js reports every internal failure as the same generic “misconfigured” sentence and the browser gives you nothing to go on:
curl -s https://your-domain.example/api/healthIt answers the questions that error cannot. database.ok false with an error code means the deployment cannot reach Postgres at all; ENETUNREACH or ENOTFOUND points straight at the IPv6 problem below. database.tables below seven means it connected but was never migrated. database.canWrite false means the role can read but not create users. auth.secret false means AUTH_SECRET is missing, which produces the identical message. auth.providers empty means no credentials.
Everything it returns is a boolean, a count, a duration or an error code. No connection string, no secret, no hostname.
Works locally, fails deployed
The specific shape of this one: “This deployment’s sign-in is misconfigured” in production, with the identical environment variables that work on your machine.
The usual cause is not the auth configuration at all. It is DATABASE_URL pointing at Supabase’s direct db.<ref>.supabase.co endpoint, which resolves to an IPv6 address only. Your laptop has IPv6, so it connects. Vercel’s functions do not, so they cannot. Auth.js reaches for the adapter, the adapter cannot reach Postgres, and what arrives in the browser is a generic configuration error that never mentions a database.
Confirm it in a terminal:
# no output means no IPv4 address, and no route from Vercel
dig +short A db.YOUR_REF.supabase.coThe fix is a pooler URI, from Project Settings → Database. Note that the username changes to postgres.<project-ref>:
DATABASE_URL="postgresql://postgres.REF:PASSWORD@aws-0-REGION.pooler.supabase.com:6543/postgres?sslmode=require"Redeploy afterwards. DATABASE_URL is read at run time, but a running deployment will not pick up a changed variable on its own.
If the database is reachable and the error persists, check that AUTH_SECRET is actually set in the deployed environment. A missing secret produces the same message.
Sign-in fails
UntrustedHost
AUTH_TRUST_HOST="true". Auth.js will not derive callback URLs from the Host header without it, and every host except Vercel needs it set explicitly.redirect_uri_mismatch means the exact callback URL is not registered with the provider. It must match character for character, including the scheme and any port: https://your-domain.example/api/auth/callback/google, or .../callback/github. Remember that a GitHub OAuth App holds only one callback URL, so development and production need separate apps.
“No providers configured” means neither credential pair is set. The sign-in page names the variables it is looking for. See Running your own.
Build-time variables
If a device sits on Connecting and never joins the room, check that NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY are set in the build environment: they are inlined at build time, so setting them only at runtime leaves the client with nothing to connect to.
db:push crashes with a TypeError
If npm run db:push stops during Pulling schema from database with something like TypeError: Cannot read properties of undefined (reading ‘replace’) pointing inside drizzle-kit/bin.cjs, the problem is the connection, not your schema.
Supabase’s transaction pooler on port 6543 is the right choice for the app and the wrong one for the Drizzle CLI. The CLI introspects by firing a burst of small per-table queries, and on that pooler some answers come back matched to the wrong question: the check-constraint reader is handed a row from the foreign-key query, which has no definition to read. It only becomes fatal once the schema contains a single CHECK constraint anywhere, because until then that code never runs, so it appears the day you add one and looks like your fault.
drizzle.config.ts already handles this by using port 5432 for CLI work, which keeps one connection for the whole run. If your setup does not match that substitution, set DIRECT_DATABASE_URL to a session-mode connection and it will be used instead. Nothing about the app’s own connection changes.