BookStackApp/BookStack · error · LoginAttemptException

$exception->getMessage()

Error message

$exception->getMessage()

What it means

LoginAttemptException rethrown in LdapSessionGuard::attempt wrapping a UserRegistrationException that occurred while creating a new local user from LDAP details. The original registration message (e.g. missing email, invalid details) is surfaced as a login failure. This library throws it because the LDAP user could not be provisioned locally.

Source

Thrown at app/Access/Guards/LdapSessionGuard.php:82

        $username = $credentials['username'];
        $userDetails = $this->ldapService->getUserDetails($username);

        $user = null;
        if (isset($userDetails['uid'])) {
            $this->lastAttempted = $user = $this->provider->retrieveByCredentials([
                'external_auth_id' => $userDetails['uid'],
            ]);
        }

        if (!$this->ldapService->validateUserCredentials($userDetails, $credentials['password'])) {
            return false;
        }

        if (is_null($user)) {
            try {
                $user = $this->createNewFromLdapAndCreds($userDetails, $credentials);
            } catch (UserRegistrationException $exception) {
                throw new LoginAttemptException($exception->getMessage());
            }
        }

        if (!($user instanceof User)) {
            throw new LoginAttemptException('Could not find or create a user for LDAP login.');
        }

        // Sync LDAP groups if required
        if ($this->ldapService->shouldSyncGroups()) {
            $this->ldapService->syncGroups($user, $username);
        }

        // Attach avatar if non-existent
        if (!$user->avatar()->exists()) {
            $this->ldapService->saveAndAttachAvatar($user, $userDetails);
        }

        $this->login($user, $remember);

View on GitHub (pinned to 18f8469a1c)

Solutions

  1. Read the wrapped message: it states the exact registration failure (e.g. missing email)
  2. Ensure LDAP users have a mail attribute, or configure a fallback email (e.g. 'email' => attribute/default) in the LDAP config
  3. Check for email collisions with existing local users and resolve duplicates
  4. Verify registration settings (auto-register on, allowed email domains) permit LDAP user creation
Defensive patterns

Strategy: try-catch

Validate before calling

if (empty($ldapUserDetails['email']) && empty($credentials['email'] ?? null)) {
    throw new \InvalidArgumentException('LDAP user has no email; cannot provision.');
}

Type guard

function isProvisionable(array $ldapDetails, array $creds): bool {
    return !empty(trim($ldapDetails['email'] ?? '')) || !empty($creds['email'] ?? null);
}

Try / catch

try {
    auth()->attempt($credentials);
} catch (\BookStack\Access\Exceptions\LoginAttemptException $e) {
    return back()->with('error', $e->getMessage());
}

Prevention

When it happens

Trigger: First-time LDAP login for a user with no local User record where createNewFromLdapAndCreds (or the underlying registration service) throws UserRegistrationException — commonly because the LDAP record lacks an email and no fallback email was provided, or the email collides with an existing account.

Common situations: LDAP users without a mail attribute; multiple LDAP users mapping to the same email violating uniqueness; auto-registration disabled or restricted by email domain; user data sanitization rejecting characters from the LDAP record.

Related errors


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