BookStackApp/BookStack · error · LoginAttemptException

Could not find or create a user for LDAP login.

Error message

Could not find or create a user for LDAP login.

What it means

LoginAttemptException thrown in LdapSessionGuard::attempt when, after searching LDAP, $user is still not an instance of User. This is a defensive post-condition: neither an existing local user matching the credentials nor a newly created one could be obtained. The library throws it so the login fails explicitly instead of proceeding with a non-user value.

Source

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

            $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);

        return true;
    }

    /**

View on GitHub (pinned to 18f8469a1c)

Solutions

  1. Verify the LDAP base DN and user search filter in config so the username resolves to an actual directory entry
  2. Check that the external_auth_id stored on existing users still matches the LDAP uid attribute
  3. Test with the LDAP debug/dump option to see what attributes are returned for the user
  4. Ensure the credentials entered match a real, active LDAP account
Defensive patterns

Strategy: try-catch

Validate before calling

$details = $ldap->getUserWithAttributes($username);
if ($details === null || empty($details['uid'])) {
    abort(401, 'No matching LDAP user');
}

Try / catch

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

Prevention

When it happens

Trigger: attempt() completes the LDAP lookup and the user-creation branch, yet $user remains null/non-User — e.g. the LDAP query returned no attributes/user, or a code path returned null without throwing a UserRegistrationException.

Common situations: LDAP bind succeeds but the search filter/base DN matches no entry for the entered username; external auth ID stored locally doesn't match the LDAP uid after LDAP directory changes; custom overrides or older data shapes returning null from the lookup.

Related errors


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