{"record":{"id":"3dee854a0406e419","repo":"pentaho/pentaho-kettle","slug":"ldapconnection-error-search","errorCode":"LDAPConnection.Error.Search","errorMessage":"LDAPConnection.Error.Search","messagePattern":"LDAPConnection\\.Error\\.Search","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"plugins/ldap/impl/src/main/java/org/pentaho/di/trans/steps/ldapinput/LDAPConnection.java","lineNumber":270,"sourceCode":"        }\n      }\n\n      if ( nrCtl > 0 ) {\n        Control[] ctls = new Control[nrCtl];\n        int index = 0;\n        if ( ctlk != null ) {\n          ctls[index++] = ctlk;\n        }\n        if ( ctlp != null ) {\n          ctls[index++] = ctlp;\n        }\n        getInitialContext().setRequestControls( ctls );\n      }\n      // Search for objects using the filter\n      this.results = getInitialContext().search( getSearchBase(), getFilter(), getSearchControls() );\n\n    } catch ( Exception e ) {\n      throw new KettleException( BaseMessages.getString( \"LDAPConnection.Error.Search\" ), e );\n    }\n  }\n\n  public int delete( String dn, boolean checkEntry ) throws KettleException {\n    try {\n\n      if ( checkEntry ) {\n        // First Check entry\n        getInitialContext().lookup( dn );\n      }\n      // The entry exists\n      getInitialContext().destroySubcontext( dn );\n      if ( log.isDebug() ) {\n        log.logDebug( BaseMessages.getString( PKG, \"LDAPinput.Exception.Deleted\", dn ) );\n      }\n      return STATUS_DELETED;\n    } catch ( NameNotFoundException n ) {\n      // The entry is not found","sourceCodeStart":252,"sourceCodeEnd":288,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/plugins/ldap/impl/src/main/java/org/pentaho/di/trans/steps/ldapinput/LDAPConnection.java#L252-L288","documentation":"LDAPConnection.search() wraps any exception from the JNDI InitialContext.search() call (LDAP search against the configured search base with the configured filter) in a KettleException with message key 'LDAPConnection.Error.Search'. The root cause is preserved as the cause, so the underlying LDAP error code (e.g. invalid DN, invalid filter, connection failure, size/time limit) is in e.getCause().","triggerScenarios":"Calling search() (directly or via getFields during transformation initialization) when: the search base DN does not exist or is malformed; the filter string is not a valid LDAP filter; the LDAP server is unreachable or credentials fail; search controls (scope, size limit, time limit) are invalid.","commonSituations":"Typo or trailing spaces in the Search Base DN (e.g. 'dc=example,dc=com' written as 'dc=example, dc=com' is fine but 'dc=example' is not); unbalanced parentheses in the filter like '(objectClass' instead of '(objectClass=*)'; searching with an attribute that doesn't exist combined with an invalid filter; firewall/SSL misconfiguration preventing connection; anonymous bind rejected by the directory.","solutions":["Inspect e.getCause() to get the real javax.naming exception (CommunicationException, NameNotFoundException, InvalidSearchFilterException, AuthenticationException) and fix accordingly.","Validate the search base DN with ldapsearch, e.g. ldapsearch -H ldap://host -D user -w pass -b 'dc=example,dc=com' '(objectClass=*)'.","Check the filter for balanced parentheses and a valid 'name=value' form.","Verify host, port, username, password and SSL settings in the step/connection config.","Test network reachability: telnet/nc to the LDAP port (389/636)."],"exampleFix":"// before\nconnection.setFilter(\"(objectClass\");\n// after\nconnection.setFilter(\"(objectClass=person)\");","handlingStrategy":"try-catch","validationCode":"// Validate before searching\nif (searchBase == null || searchBase.trim().isEmpty()) throw new KettleException(\"Search base is empty\");\nif (filter == null || !balancedParentheses(filter)) throw new KettleException(\"Invalid LDAP filter: \" + filter);\n// then smoke-test with: ldapsearch -H ldap://host -D user -w pass -b \"$searchBase\" \"$filter\"","typeGuard":null,"tryCatchPattern":"try {\n  connection.search();\n} catch (KettleException e) {\n  Throwable root = ExceptionUtils.getRootCause(e);\n  if (root instanceof CommunicationException) { /* fix host/port/SSL */ }\n  else if (root instanceof InvalidSearchFilterException) { /* fix filter */ }\n  else if (root instanceof NameNotFoundException) { /* fix search base DN */ }\n  else if (root instanceof AuthenticationException) { /* fix credentials */ }\n  throw e;\n}","preventionTips":["Always validate base DN and filter with ldapsearch before configuring the step","Keep credentials and SSL config in a shared, tested connection definition","Log the root cause (e.getCause()) not just the Kettle message","Verify network/firewall access to the LDAP port from the transformation host"],"tags":["ldap","kettle","search","jndi"],"backgroundTag":"ldap-search-failed","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}