Login Works but Signup Does Not

Written By
SprintX Team
AI & Product Engineering
August 08, 2026
6 min read

Signup is a longer chain than login — email, database rows, triggers, and policies all have to succeed. Here is how to find which link in that chain is broken.
You log in fine. Your co-founder logs in fine. Every test account you created during development logs in fine. Then a real person tries to sign up and the button spins, or throws a vague "something went wrong", or — the worst version — appears to succeed and lands them on a broken dashboard with no data.
This asymmetry confuses founders because it feels like auth is either working or it is not. It is not one thing. Login is a short chain: verify a credential, mint a session. Signup is a long one: validate input, create an auth record, send an email, create a profile row, apply a default role, redirect. Login exercises maybe three of those links. Signup exercises all of them, and every account you already have was created before whatever broke, broke.
Here is how to find the specific link that is failing, in the order that finds it fastest.
Get the real error first
Almost every "signup is broken" ticket we pick up starts with a generic client-side message because the code does something like catching the error and showing a friendly string. Before theorizing, get the actual response.
Open DevTools, go to the Network tab, attempt a signup with a fresh email address, and read the response body of the failing request — not the status code alone. Auth providers return quite specific messages: "User already registered", "Database error saving new user", "Email rate limit exceeded", "Password should be at least 6 characters". Each of those points at a completely different fix.
If the network request never fires at all, your problem is client-side validation or a form handler that is not wired up, and nothing below applies. If the request returns 200 but the user cannot use the app, skip to the profile-row section.
The eight things that break signup but not login
1. Email delivery is dead
If your provider requires email confirmation, signup depends on an outbound email that login does not. Most hosted auth services ship with a shared demo mailer that is heavily rate-limited — fine for your three test accounts, useless the moment real users arrive. The signup call succeeds, no email arrives, and the account sits unconfirmed forever.
The fix is to configure your own SMTP or transactional provider with a verified sending domain. If mail is your bottleneck, the delivery-side failures are covered in detail in why transactional emails are not arriving.
2. A database trigger fails after the auth record is created
This one produces the infamous "Database error saving new user". A trigger fires on new auth users to insert a matching row in a profiles table. If that insert violates a not-null constraint, a unique index, or a foreign key, the whole signup transaction rolls back. Login never touches the trigger, so it is unaffected.
The tell: the error appears instantly, with no network latency, and mentions the database rather than the credential. Read the database logs directly — the constraint name is in there, and it names the exact column.
3. Row-level security blocks the insert
Your policies allow authenticated users to read and update their own rows. Nobody wrote the insert policy, or the insert policy checks a user id that does not exist yet at the moment of insert. The result is a signup that completes on the auth side and fails on the application side, leaving a user with a session but no profile.
This is the single most common auth bug we see in Supabase apps built by AI tools, because generated policies cover the read path and stop there. Supabase RLS mistakes in AI-generated apps covers the pattern, and how row-level security and roles fit together covers writing policies that handle creation properly.
4. Signups are disabled or restricted in the provider settings
Worth ruling out in ten seconds. Many auth dashboards have an "allow new users to sign up" toggle, a domain allow-list, or an invite-only mode. Someone flips it during development to stop spam and nobody flips it back. Login is unaffected because those users already exist.
5. The redirect URL is not on the allow-list
Confirmation and magic links carry a redirect target. Providers refuse targets that are not explicitly allowed, and the default allow-list usually contains localhost only. The user clicks the link in the email and lands on an error page or back at the login screen, which reads to them as "signup did not work".
Add every production and preview domain to the redirect allow-list, and make sure your app is sending its production URL rather than a value baked in at build time from a local file.
6. The email already exists in a form you cannot see
Providers deliberately avoid confirming which addresses are registered, so a repeat signup may return a success-shaped response that creates nothing. If you have been testing with the same address, you may be hitting an unconfirmed account from an earlier attempt. Always test with a genuinely fresh address, and check the auth users table before concluding anything.
7. Rate limits on the auth endpoint
Hosted auth has per-hour caps on signups and emails per IP or per project. Testing signup twenty times in a row will get you throttled, and then everything looks broken for the next hour — including for real users behind the same IP. Read the response headers; throttling is explicit when you look for it.
8. The password rule mismatch
Your form validates six characters. The provider requires eight, or a symbol, or rejects passwords found in breach lists. Client validation passes, server validation rejects, and if the error is swallowed the user sees a spinner that stops. Mirror the provider's exact rules in the form, and surface the server message verbatim when it disagrees.
Which symptom means which cause
| What the user sees | Most likely cause | First place to look |
|---|---|---|
| Button spins, nothing happens | Swallowed server error | Network tab response body |
| "Database error saving new user" | Trigger or constraint failure | Database logs |
| Success, then an empty dashboard | Missing profile row or insert policy | Profiles table plus RLS policies |
| No confirmation email ever arrives | SMTP not configured, or rate limited | Auth provider email logs |
| Email arrives, link lands on an error | Redirect URL not allow-listed | Auth provider URL configuration |
| "User already registered" on a new email | Unconfirmed prior attempt | Auth users table |
Test signup like a stranger, not like the founder
The reason this bug survives to production is that nobody on the team ever signs up again. Two habits fix that permanently.
First, use a fresh address in a private window every time you touch anything in the auth path — plus-addressing (you+test1@yourdomain.com) gives you infinite disposable addresses that still deliver to your inbox.
Second, make signup an automated test. One end-to-end test that registers a new user, follows the confirmation flow, and asserts that the profile row exists catches every one of the eight causes above before a deploy goes out. If your app has no test coverage today, adding tests to a codebase you did not write shows where to start, and signup is exactly the flow to start with.
Finally, treat the "session but no profile" state as a bug in its own right. Users who reach it are stuck permanently — they cannot sign up again because the account exists, and they cannot use the app because the row does not. A repair path that creates the missing row on first login is worth writing once.
Frequently asked questions
Why does signup work locally and fail in production? Local development usually points at a different auth project, skips email confirmation, has a permissive redirect allow-list, and runs without production security policies. Every one of those differences is a place signup can break in production only. Point a staging environment at production-equivalent settings and the gap disappears.
Users get a session but the app shows no data. Is that a signup bug? Yes, and a common one. The auth record was created and the profile row was not, so every query filtered by profile returns nothing. Check whether a row exists in your users or profiles table for that account; if it does not, look at the trigger and the insert policy.
Should I turn off email confirmation to unblock signups? As a temporary measure while you fix delivery, sometimes — but understand the tradeoff: you are accepting unverified addresses, which means bounced billing emails, unrecoverable accounts, and a spam-signup surface. Fix the mail configuration and turn confirmation back on.
If new users cannot get into an app that works perfectly for you, the break is somewhere in a chain nobody has traced end to end. SprintX audits and repairs auth flows in AI-generated apps — triggers, policies, email, and redirects — and leaves behind a test that keeps signup honest. Send us your repo or builder link.


