{"record":{"id":"883be8ba619df5bb","repo":"risingwavelabs/risingwave","slug":"ldap-bind-failed","errorCode":null,"errorMessage":"LDAP bind failed","messagePattern":"LDAP bind failed","errorType":"exception","errorClass":"PsqlError","httpStatus":null,"severity":"error","filePath":"src/utils/pgwire/src/ldap_auth.rs","lineNumber":532,"sourceCode":"            .await\n            .map_err(|e| {\n                PsqlError::StartupError(anyhow!(e).context(\"LDAP search failed\").into())\n            })?;\n\n        // If no user found, authentication fails\n        let search_entries: Vec<SearchEntry> =\n            rs.0.into_iter().map(SearchEntry::construct).collect();\n        if search_entries.is_empty() {\n            return Ok(false);\n        }\n\n        // Attempt to bind with the user's DN and password\n        let user_dn = &search_entries[0].dn;\n\n        let bind_result = ldap\n            .simple_bind(user_dn, password)\n            .await\n            .map_err(|e| PsqlError::StartupError(anyhow!(e).context(\"LDAP bind failed\").into()));\n\n        // Explicitly unbind the connection\n        let _ = ldap.unbind().await;\n\n        let bind_result = bind_result?;\n        match bind_result.success() {\n            Ok(_) => Ok(true),\n            Err(e) => {\n                tracing::error!(error = %e.as_report(), \"LDAP bind unsuccessful\");\n                Err(PsqlError::StartupError(\n                    anyhow!(e).context(\"LDAP bind failed\").into(),\n                ))\n            }\n        }\n    }\n\n    /// Simple bind authentication\n    async fn simple_bind(&self, username: &str, password: &str) -> PsqlResult<bool> {","sourceCodeStart":514,"sourceCodeEnd":550,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/utils/pgwire/src/ldap_auth.rs#L514-L550","documentation":"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.","triggerScenarios":"ldap.simple_bind(user_dn, password) returns Err (mapped here), or later bind_result.success() yields an error result code like invalidCredentials","commonSituations":"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).","solutions":["Have the user retry with the correct directory password (this is usually simple credential failure)","Verify the matched DN can bind: ldapwhoami -D 'user_dn' -w 'password'","Use ldaps:// or StartTLS if the directory rejects simple binds over insecure connections","Tighten search_filter so only bindable user objects match (e.g. add (objectClass=user))"],"exampleFix":"// before: filter matches groups too\nsearch_filter = '(cn={username})'\n// after: restrict to user objects\nsearch_filter = '(&(objectClass=user)(sAMAccountName={username}))'","handlingStrategy":"try-catch","validationCode":"// confirm a test user DN can bind before pointing RisingWave at the directory\n# ldapwhoami -H ldaps://ldap.corp:636 -D 'cn=testuser,ou=users,dc=corp,dc=com' -w 'password'","typeGuard":null,"tryCatchPattern":"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","preventionTips":["Restrict search_filter to bindable user objects with (objectClass=user) etc.","Communicate that passwords are directory passwords, not RisingWave-local ones","Use ldaps:// or StartTLS since many directories reject simple binds over plaintext","Map expired/locked account result codes to user-friendly messages"],"tags":["ldap","authentication","bind","credentials"],"backgroundTag":"authentication-required","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}