BookStackApp/BookStack · critical · LdapException
($isAnonymous ? trans('errors.ldap_fail_anonymous') : trans(
Error message
($isAnonymous ? trans('errors.ldap_fail_anonymous') : trans('errors.ldap_fail_authed')) What it means
LdapException thrown by LdapService::bindSystemUser when the LDAP bind call fails. The message distinguishes anonymous binding (ldap_fail_anonymous) from authenticated binding with a DN/password (ldap_fail_authed), pointing at either bad credentials or an LDAP server refusing the bind.
Source
Thrown at app/Access/LdapService.php:207
*
* @param resource|\LDAP\Connection $connection
*
* @throws LdapException
*/
protected function bindSystemUser($connection): void
{
$ldapDn = $this->config['dn'];
$ldapPass = $this->config['pass'];
$isAnonymous = ($ldapDn === false || $ldapPass === false);
if ($isAnonymous) {
$ldapBind = $this->ldap->bind($connection);
} else {
$ldapBind = $this->ldap->bind($connection, $ldapDn, $ldapPass);
}
if (!$ldapBind) {
throw new LdapException(($isAnonymous ? trans('errors.ldap_fail_anonymous') : trans('errors.ldap_fail_authed')));
}
}
/**
* Get the connection to the LDAP server.
* Creates a new connection if one does not exist.
*
* @throws LdapException
*
* @return resource|\LDAP\Connection
*/
protected function getConnection()
{
if ($this->ldapConnection !== null) {
return $this->ldapConnection;
}
// Check LDAP extension in installedView on GitHub (pinned to 18f8469a1c)
Solutions
- Verify the LDAP bind DN and password in the LDAP configuration are correct and current
- If using anonymous bind, enable anonymous bind on the LDAP server or configure a dedicated bind user
- Test credentials with ldapsearch/ldapwhoami outside the app to isolate the issue
- Check the bind account is not locked/expired and has read access to the search base
Defensive patterns
Strategy: try-catch
Validate before calling
$test = @ldap_connect($config['server']);
$ok = $test && @ldap_bind($test, $config['dn'], $config['pass']);
if (!$ok) { throw new RuntimeException('LDAP bind credentials invalid'); } Try / catch
try {
$user = $ldapService->getUserWithAttributes($username);
} catch (\BookStack\Exceptions\LdapException $e) {
report($e);
return back()->with('error', trans('errors.ldap_fail_authed'));
} Prevention
- Store bind credentials in env/config secrets and rotate deliberately
- Test binds with ldapwhoami after any credential or server change
- Avoid anonymous binds; use a dedicated read-only service account
When it happens
Trigger: bindSystemUser (called via getUserWithAttributes and getParentsOfGroup) runs and $this->ldap->bind() returns false: wrong LDAP admin DN/password configured, anonymous bind attempted but disallowed by the server, or the bind user lacks permission.
Common situations: Typo or password rotation of the LDAP bind/admin credentials in config; server configuration disallows anonymous binds (common default in AD/OpenLDAP); special characters in the DN/password mishandled; LDAP service account locked out or expired.
Related errors
- $exception->getMessage()
- Could not find or create a user for LDAP login.
- 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/ededf6935cd6d954.
Report an issue: GitHub.