BookStackApp/BookStack · warning · UserRegistrationException
auth.registration_email_domain_invalid
Error message
auth.registration_email_domain_invalid
What it means
This UserRegistrationException is thrown by RegistrationService::ensureEmailDomainAllowed when the domain part of the registering user's email is not in the comma-separated 'registration-restrict' setting (Settings > Registration > 'Restrict email domains'). The code extracts everything after the last '@' via mb_strrchr and does a strict in_array comparison against the configured domain list; on mismatch it throws with translated message 'auth.registration_email_domain_invalid' and redirects to /register (if open registration) or /login. Registration is blocked entirely for that email.
Source
Thrown at app/Access/RegistrationService.php:144
* Ensure that the given email meets any active email domain registration restrictions.
* Throws if restrictions are active and the email does not match an allowed domain.
*
* @throws UserRegistrationException
*/
protected function ensureEmailDomainAllowed(string $userEmail): void
{
$registrationRestrict = setting('registration-restrict');
if (!$registrationRestrict) {
return;
}
$restrictedEmailDomains = explode(',', str_replace(' ', '', $registrationRestrict));
$userEmailDomain = mb_substr(mb_strrchr($userEmail, '@'), 1);
if (!in_array($userEmailDomain, $restrictedEmailDomains)) {
$redirect = $this->registrationAllowed() ? '/register' : '/login';
throw new UserRegistrationException(trans('auth.registration_email_domain_invalid'), $redirect);
}
}
}
View on GitHub (pinned to 18f8469a1c)
Solutions
- Check Settings > Registration (or the 'registration-restrict' setting in the DB) and ensure the user's email domain exactly matches one entry of the comma-separated list; fix typos, stray spaces, or wrong domains.
- If subdomain emails should be allowed, add the subdomain explicitly (e.g. 'example.com,mail.example.com') — the check is exact equality, not suffix-based.
- If the user is legitimate and cannot change email, have an admin create the account manually via the Users admin page, which bypasses domain restriction.
- If domain restriction is no longer wanted, clear the 'Restrict email domains' field so ensureEmailDomainAllowed returns early.
- Consider a theme event (AUTH_PRE_REGISTER) or custom code if you need smarter matching (case-insensitive/suffix) than the built-in exact check.
Example fix
// before (registration-restrict setting) example.com, example.org , // after (normalized, includes subdomain actually used) example.com,mail.example.com,example.org
Defensive patterns
Strategy: validation
Validate before calling
// Mirror the server-side check before submitting registration:
$restrict = setting('registration-restrict');
if ($restrict) {
$allowed = explode(',', str_replace(' ', '', $restrict));
$domain = mb_substr(mb_strrchr($email, '@'), 1);
if (!in_array($domain, $allowed, true)) {
throw new \InvalidArgumentException("Email domain '{$domain}' is not allowed");
}
} Try / catch
use BookStack\Exceptions\UserRegistrationException;
try {
$user = $registrationService->registerUser($userData);
} catch (UserRegistrationException $e) {
if (str_contains($e->getMessage(), 'domain')) {
return redirect($e->getRedirect())->withErrors(['email' => trans('auth.registration_email_domain_invalid')]);
}
throw $e;
} Prevention
- Normalize the registration-restrict list: no stray spaces or trailing commas, consistent lowercase
- Remember the match is exact — list every subdomain users actually use
- Show allowed domains on the registration form so users pick compliant emails
- Periodically audit the setting against real user email domains
When it happens
Trigger: setting('registration-restrict') is non-empty (e.g. 'mycompany.com,subsidiary.com') and the submitted email's domain after '@' does not exactly match one of the comma-separated entries — e.g. user emails from 'mail.mycompany.com', a subdomain, different casing rules, or a trailing space/comma typo in the setting, or the email has no '@' (mb_strrchr returns false → substring of garbage).
Common situations: Organizations restricting sign-ups to a corporate domain but users registering with a personal Gmail address; admins listing subdomains that don't match (restriction is exact-string, not suffix match); whitespace or case mismatches in the configured list; invited contractors with @partner.example.com addresses while only @example.com is allowed; SAML/OAuth flows where the IdP email uses a different domain than expected.
Related errors
- auth.email_confirm_send_error
- errors.image_upload_replace_type
- Book to move chapter into not found
- Book or chapter to move page into not found
- Selected parent is not a book or chapter
AI-assisted analysis of BookStackApp/BookStack@18f8469a1c (2026-09-02).
Data as JSON: /api/errors/8e554bd3c70adab0.
Report an issue: GitHub.