toeverything/AFFiNE · error · SignUpForbidden
sign_up_forbidden
sign_up_forbidden
Error message
You are not allowed to sign up.
What it means
In assertSignupAllowed (reached from send when no existing user matches the email), if config.auth.allowSignup is false the server throws SignUpForbidden. This is the global signup toggle: when off, brand-new emails cannot initiate a magic-link sign-in because account creation is disabled. Existing users are unaffected (they never reach this branch).
Source
Thrown at packages/backend/server/src/core/auth/magic-link.ts:135
TokenType.SignIn,
consumed.token,
{
credential: email,
}
);
if (!tokenRecord) {
throw new InvalidEmailToken();
}
const user = await this.models.user.fulfill(email);
return { userId: user.id, method: 'magic_link' };
}
private async assertSignupAllowed(email: string) {
if (!this.config.auth.allowSignup) {
throw new SignUpForbidden();
}
if (!this.config.auth.requireEmailDomainVerification) {
return;
}
if (!(await verifyEmailDomainRecords(email))) {
throw new InvalidEmail({ email });
}
}
}
View on GitHub (pinned to 26c515e050)
Solutions
- Set config.auth.allowSignup=true (AFFiNE_AUTH_ALLOW_SIGNUP=true) and redeploy if self-registration is desired.
- Provision the user account through admin tooling / invitation instead of self-signup.
- Sign in with an existing account rather than attempting to register a new email.
- Confirm the email is not typo'd — an existing user with a slightly different email won't match.
Example fix
# enable self-signup AFFiNE_AUTH_ALLOW_SIGNUP=true
Defensive patterns
Strategy: validation
Type guard
function isSignUpForbidden(err: unknown): boolean {
return (
!!err &&
typeof err === 'object' &&
(err as { code?: string }).code === 'sign_up_forbidden'
);
} Try / catch
try {
await magicLink.send(email);
} catch (err) {
if (isSignUpForbidden(err)) {
showUser('Sign-up is disabled. Contact your administrator.');
return;
}
throw err;
} Prevention
- Gate the sign-up UI on whether allowSignup is enabled (expose via a capabilities endpoint).
- On self-hosted, set AFFiNE_AUTH_ALLOW_SIGNUP explicitly to the desired value.
- Provision accounts via admin invitation when allowSignup is off.
- Tell users to use an existing account when registration is closed.
When it happens
Trigger: config.auth.allowSignup === false AND the email has no user row AND send() is called. Typical of self-hosted deployments that disable open registration.
Common situations: Self-hosted admin set AFFiNE_AUTH_ALLOW_SIGNUP=false (or omitted enabling it). A private deployment where accounts are provisioned out-of-band. Someone tries to self-register on an invite-only instance.
Related errors
- invalid_email
- ErrorCode.ValueNotExists
- unsupported_client_version
- action_forbidden
- invalid_app_config_input
AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12).
Data as JSON: /api/errors/95dcf65d41d3ae56.
Report an issue: GitHub.