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

  1. 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.
  2. 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.
  3. 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.
  4. If domain restriction is no longer wanted, clear the 'Restrict email domains' field so ensureEmailDomainAllowed returns early.
  5. 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

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


AI-assisted analysis of BookStackApp/BookStack@18f8469a1c (2026-09-02). Data as JSON: /api/errors/8e554bd3c70adab0. Report an issue: GitHub.