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
- Verify the LDAP base DN and user search filter in config so the username resolves to an actual directory entry
- Check that the external_auth_id stored on existing users still matches the LDAP uid attribute
- Test with the LDAP debug/dump option to see what attributes are returned for the user
- 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
- Validate base DN and search filters with ldapsearch before configuring the app
- Re-sync external_auth_id values after LDAP directory migrations
- Enable LDAP debug logging when diagnosing login failures
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
- $exception->getMessage()
- ($isAnonymous ? trans('errors.ldap_fail_anonymous') : trans(
- errors.ldap_extension_not_installed
- errors.ldap_cannot_connect
- Could not start TLS connection. Further details in the appli
AI-assisted analysis of BookStackApp/BookStack@18f8469a1c (2026-09-02).
Data as JSON: /api/errors/5ce0b59e1e3de64a.
Report an issue: GitHub.