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 installed

View on GitHub (pinned to 18f8469a1c)

Solutions

  1. Verify the LDAP bind DN and password in the LDAP configuration are correct and current
  2. If using anonymous bind, enable anonymous bind on the LDAP server or configure a dedicated bind user
  3. Test credentials with ldapsearch/ldapwhoami outside the app to isolate the issue
  4. 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

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


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