calcom/cal.diy · warning · HttpError
Signup is disabled
Error message
Signup is disabled
What it means
Thrown by the /api/auth/signup route (HttpError, HTTP 403) in ensureEnvironmentForSignup when either NEXT_PUBLIC_DISABLE_SIGNUP env is 'true' or the FeaturesRepository reports the 'disable-signup' feature flag is globally enabled. Team-invite signups (valid token) bypass this gate entirely.
Source
Thrown at apps/web/app/api/auth/signup/route.ts:32
import { checkCfTurnstileToken } from "@calcom/lib/server/checkCfTurnstileToken";
import { prisma } from "@calcom/prisma";
import { signupSchema } from "@calcom/prisma/zod-utils";
async function ensureSignupIsEnabled(body: Record<string, string>) {
const { token } = signupSchema
.pick({
token: true,
})
.parse(body);
// Still allow signups if there is a team invite
if (token) return;
const featuresRepository = new FeaturesRepository(prisma);
const signupDisabled = await featuresRepository.checkIfFeatureIsEnabledGlobally("disable-signup");
if (process.env.NEXT_PUBLIC_DISABLE_SIGNUP === "true" || signupDisabled) {
throw new HttpError({
statusCode: 403,
message: "Signup is disabled",
});
}
}
async function handler(req: NextRequest) {
const remoteIp = getIP(req);
// Use a try catch instead of returning res every time
try {
// Rate limit: 10 signups per 60 seconds per IP
await checkRateLimitAndThrowError({
rateLimitingType: "core",
identifier: `api:signup:${piiHasher.hash(remoteIp)}`,
});
const body = await parseRequestData(req);
const query = Object.fromEntries(req.nextUrl.searchParams.entries());View on GitHub (pinned to 176037d0af)
Solutions
- If public signup should be on, unset NEXT_PUBLIC_DISABLE_SIGNUP (or set to 'false') and disable the 'disable-signup' feature flag.
- If signup is intentionally disabled, accept invite-only flow: always sign up with a valid team-invite token so ensureEnvironmentForSignup returns early.
- Surface a clear 'registration is closed' message on 403 instead of retrying.
Example fix
// before
await signup({ username, email }); // fails 403 when disabled
// after
if (!inviteToken) {
showNotice('Public registration is disabled. Use your team invite link.');
return;
}
await signup({ username, email, token: inviteToken }); Defensive patterns
Strategy: validation
Validate before calling
// Detect disabled signup before attempting registration
if (!inviteToken && (process.env.NEXT_PUBLIC_DISABLE_SIGNUP === 'true')) {
showNotice('Public registration is disabled. Use your team invite link.');
return;
}
await signup({ username, email, token: inviteToken }); Try / catch
try {
await signup(payload);
} catch (e) {
if (e instanceof HttpError && e.statusCode === 403 && /Signup is disabled/.test(e.message)) {
showRegistrationClosedNotice();
return;
}
throw e;
} Prevention
- Always carry a valid team-invite token if public signup is off.
- Surface NEXT_PUBLIC_DISABLE_SIGNUP / the feature flag to the signup UI.
- Do not retry on 403; it is a policy decision, not a transient failure.
When it happens
Trigger: POST /api/auth/signup without a team-invite token while public signups are turned off via env var or feature flag.
Common situations: Self-hosted/enterprise deployment that disables public registration, a feature flag flipped in production, an env var misconfigured to 'true' unintentionally.
Related errors
- PermissionsGuard - no authentication provided. Provide eithe
- EventTypeOwnershipGuard - No user associated with the reques
- Invalid username
- Username or email is already taken
- Access denied. Either the team with ID=${teamId} does not ow
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/f1d64c88a210b74f.
Report an issue: GitHub.