BookStackApp/BookStack · error · UserRegistrationException
errors.auth_pre_register_theme_prevention
Error message
errors.auth_pre_register_theme_prevention
What it means
registerUser() dispatches the AUTH_PRE_REGISTER theme event, allowing custom theme code to veto registration by returning exactly false. When that happens, BookStack throws UserRegistrationException with the translated 'errors.auth_pre_register_theme_prevention' message and aborts user creation.
Source
Thrown at app/Access/RegistrationService.php:93
*/
public function registerUser(array $userData, ?SocialAccount $socialAccount = null, bool $emailConfirmed = false): User
{
$userEmail = $userData['email'];
$authSystem = $socialAccount ? $socialAccount->driver : auth()->getDefaultDriver();
// Email restriction
$this->ensureEmailDomainAllowed($userEmail);
// Ensure the user does not already exist
$alreadyUser = !is_null($this->userRepo->getByEmail($userEmail));
if ($alreadyUser) {
throw new UserRegistrationException(trans('errors.error_user_exists_different_creds', ['email' => $userEmail]), '/login');
}
/** @var ?bool $shouldRegister */
$shouldRegister = Theme::dispatch(ThemeEvents::AUTH_PRE_REGISTER, $authSystem, $userData);
if ($shouldRegister === false) {
throw new UserRegistrationException(trans('errors.auth_pre_register_theme_prevention'), '/login');
}
// Create the user
$newUser = $this->userRepo->createWithoutActivity($userData, $emailConfirmed);
$newUser->attachDefaultRole();
// Assign a social account if given
if ($socialAccount) {
$newUser->socialAccounts()->save($socialAccount);
}
Activity::add(ActivityType::AUTH_REGISTER, $socialAccount ?? $newUser);
Theme::dispatch(ThemeEvents::AUTH_REGISTER, $authSystem, $newUser);
// Start the email confirmation flow if required
if ($this->emailConfirmationService->confirmationRequired() && !$emailConfirmed) {
$newUser->save();
View on GitHub (pinned to 18f8469a1c)
Solutions
- Inspect your theme's AUTH_PRE_REGISTER handler (functions.php / theme code) to see why it returned false
- Log inputs ($authSystem, $userData) inside the handler to identify the rejected user and reason
- Fix the handler's logic if the rejection is unintended (e.g. domain allowlist missing the user's domain)
- If intentional, communicate the block to users or adjust the allowlist; ensure the handler returns true/void (not false) to allow registration
Example fix
// before (theme functions.php — vetoes everything accidentally)
Theme::listen(ThemeEvents::AUTH_PRE_REGISTER, function ($system, $data) {
return checkAllowed($data['email']); // returns false on lookup failure
});
// after — only veto explicitly, default to allow
Theme::listen(ThemeEvents::AUTH_PRE_REGISTER, function ($system, $data) {
if (str_ends_with($data['email'], '@blocked.example.com')) {
return false;
}
return true;
}); Defensive patterns
Strategy: try-catch
Validate before calling
// Audit all theme listeners for AUTH_PRE_REGISTER and ensure they only return false deliberately: $listeners = Theme::getListeners(ThemeEvents::AUTH_PRE_REGISTER); // if exposed // Or grep your themes dir: // grep -rn "AUTH_PRE_REGISTER" themes/
Try / catch
try {
auth()->attemptOidcLogin();
} catch (BookStack\Access\Oidc\OidcException $e) {
if (str_contains($e->getMessage(), 'auth_pre_register_theme_prevention')) {
Log::info('Registration vetoed by theme hook', ['user' => $email]);
return redirect('/login')->withErrors(['theme' => 'Registration was blocked by a custom policy']);
}
throw $e;
} Prevention
- Return true (or nothing) from AUTH_PRE_REGISTER handlers to allow registration
- Log inside theme hooks so vetoes are traceable
- Test theme hooks with fresh users before deploying
- Guard async lookups in hooks so transient failures don't return false
When it happens
Trigger: registerUser() (via findOrRegister during OIDC/external login) fires Theme::dispatch(ThemeEvents::AUTH_PRE_REGISTER, $authSystem, $userData); the registered theme handler returns boolean false, causing the exception before user creation.
Common situations: A custom theme's AUTH_PRE_REGISTER hook (e.g. allowlisting domains, blocking bots, syncing to external systems) deliberately rejects the user, or the hook has a bug returning falsy/false unintentionally (e.g. returning 0, null-cast logic, or returning false from an API-check helper).
Related errors
- errors.email_already_confirmed
- {$exception->getMessage()}
- auth.registrations_disabled
- errors.error_user_exists_different_creds
- auth.email_confirm_send_error
AI-assisted analysis of BookStackApp/BookStack@18f8469a1c (2026-09-02).
Data as JSON: /api/errors/d3d5e0c9726ebb63.
Report an issue: GitHub.