risingwavelabs/risingwave · error · PsqlError

LDAP bind failed

Error message

LDAP bind failed

What it means

Once the user's DN is found, search_and_bind binds as that DN with the end-user's password to authenticate them. simple_bind errors are mapped to this StartupError before the connection is unbound; a non-success result code from bind_result.success() is then matched separately. This is the final user-credential check — a failure means the username/password supplied by the psql client are wrong for the directory, or the DN found cannot bind.

Source

Thrown at src/utils/pgwire/src/ldap_auth.rs:532

            .await
            .map_err(|e| {
                PsqlError::StartupError(anyhow!(e).context("LDAP search failed").into())
            })?;

        // If no user found, authentication fails
        let search_entries: Vec<SearchEntry> =
            rs.0.into_iter().map(SearchEntry::construct).collect();
        if search_entries.is_empty() {
            return Ok(false);
        }

        // Attempt to bind with the user's DN and password
        let user_dn = &search_entries[0].dn;

        let bind_result = ldap
            .simple_bind(user_dn, password)
            .await
            .map_err(|e| PsqlError::StartupError(anyhow!(e).context("LDAP bind failed").into()));

        // Explicitly unbind the connection
        let _ = ldap.unbind().await;

        let bind_result = bind_result?;
        match bind_result.success() {
            Ok(_) => Ok(true),
            Err(e) => {
                tracing::error!(error = %e.as_report(), "LDAP bind unsuccessful");
                Err(PsqlError::StartupError(
                    anyhow!(e).context("LDAP bind failed").into(),
                ))
            }
        }
    }

    /// Simple bind authentication
    async fn simple_bind(&self, username: &str, password: &str) -> PsqlResult<bool> {

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Have the user retry with the correct directory password (this is usually simple credential failure)
  2. Verify the matched DN can bind: ldapwhoami -D 'user_dn' -w 'password'
  3. Use ldaps:// or StartTLS if the directory rejects simple binds over insecure connections
  4. Tighten search_filter so only bindable user objects match (e.g. add (objectClass=user))

Example fix

// before: filter matches groups too
search_filter = '(cn={username})'
// after: restrict to user objects
search_filter = '(&(objectClass=user)(sAMAccountName={username}))'
Defensive patterns

Strategy: try-catch

Validate before calling

// confirm a test user DN can bind before pointing RisingWave at the directory
# ldapwhoami -H ldaps://ldap.corp:636 -D 'cn=testuser,ou=users,dc=corp,dc=com' -w 'password'

Try / catch

catch PsqlError::StartupError 'LDAP bind failed'; on invalidCredentials (49) return a clean auth-failure to the psql client rather than a startup error; log only the DN, never the password

Prevention

When it happens

Trigger: ldap.simple_bind(user_dn, password) returns Err (mapped here), or later bind_result.success() yields an error result code like invalidCredentials

Common situations: End user typed the wrong password in psql; password expired or account locked; directory disallows simple binds for user entries (e.g. AD default forbids simple bind over plaintext); the matched entry is not actually a bindable user (found a group or contact object).

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/883be8ba619df5bb. Report an issue: GitHub.