Supabase throws `signup_disabled: Signups are disabled` when the project explicitly refuses to create new accounts, so every signUp, OAuth, or OTP request returns a 400. Re-enable the "Allow new users to sign up" toggle or clear the same flag in self-hosted deployments to allow account creation again.
The `signup_disabled` code means the `disable_signup` flag inside Supabase Auth is true, usually because the "Allow new users to sign up" switch under Project Settings → Authentication → User Signups has been turned off. With that configuration, the Auth server never reaches the password or social-provider logic—every registration attempt immediately returns the error instead of sending verification emails or creating a user row, which keeps the project closed for maintenance, private beta testing, or invite-only campaigns.
Signups are controlled by a single switch in the dashboard:
1. Open https://app.supabase.com/project/_/settings/auth and sign in.
2. Navigate to Project Settings → Authentication → User Signups from the left menu.
3. Toggle Allow new users to sign up back on and click Save.
4. Wait for the "Successfully updated settings" toast, then retry supabase.auth.signUp() (or your social/OTP flow).
Use the Supabase client to read the settings and make sure signups are not suppressed on the server:
const { data, error } = await supabase.auth.getSettings();
if (error) throw error;
console.log('disable_signup', data.disable_signup);If disable_signup is true, repeat step 1; if it remains true after toggling, the project settings did not persist or you are hitting a different project.
Mistaking the project or environment is a common trap:
- Double-check SUPABASE_URL and keys in your .env files; you might still point at a staging project where signups are locked.
- For Next.js, compare .env.local with .env.production to confirm each environment uses the expected credentials.
- Log the value of process.env.NEXT_PUBLIC_SUPABASE_URL (or the equivalent in your stack) before calling signUp().
- If you deploy to multiple Supabase projects, switch between them in the dashboard to see which one allows new users.
If the project should stay closed (maintenance, beta, invite-only), catch the error on the client and show alternatives instead of surfacing a raw exception:
const { error } = await supabase.auth.signUp({ email, password });
if (error?.code === 'signup_disabled') {
showError('New user registration is temporarily disabled. Check back later or contact support.');
return;
}You can also hide the sign-up form when the dashboard toggle is off so users do not attempt a flow that will fail.
## Why signups get disabled
- Supabase stores the flag inside auth.config and uses it to short-circuit the sign-up pipeline, so the error never hits password strength checks or social providers.
- When you self-host Gotrue, set GOTRUE_DISABLE_SIGNUP=false (or remove the env var) and restart the container to allow registrations again.
- Some teams disable signups briefly during deployments or after a security incident, which is why responsive messaging and feature flags help avoid confusing error screens.
- Growing projects may combine the dashboard toggle with database triggers or hooks (before-user-created) to implement invite-only flows; make sure those hooks are not raising signup_disabled as well.
- Monitoring the spike in signup_disabled errors in Supabase logs quickly tells you whether signups were just toggled off or a new issue cropped up.
email_conflict_identity_not_deletable: Cannot delete identity because of email conflict
How to fix "Cannot delete identity because of email conflict" in Supabase
mfa_challenge_expired: MFA challenge has expired
How to fix "mfa_challenge_expired: MFA challenge has expired" in Supabase
conflict: Database conflict, usually related to concurrent requests
How to fix "database conflict usually related to concurrent requests" in Supabase
phone_exists: Phone number already exists
How to fix "phone_exists" in Supabase
StorageApiError: resource_already_exists
StorageApiError: Resource already exists