pentaho/pentaho-kettle · error · KettleException

LDAPConnection.Error.Delete

LDAPConnection.Error.Delete

Error message

LDAPConnection.Error.Delete

What it means

LDAPConnection.delete(dn, checkEntry) wraps any non-NameNotFound exception from the JNDI delete in a KettleException with message key 'LDAPConnection.Error.Delete' (dn interpolated). Typical causes are insufficient permissions, invalid DN syntax, or connectivity/schema constraints — the raw javax.naming exception is attached as cause.

Solutions

  1. Read e.getCause() (e.g. InvalidNameException, NoPermissionException) and fix the DN or permissions accordingly.
  2. Escape special characters in DN values (',' '+' '"' '\\' '<' '>' ';') or use LdapName/ldapsearch to validate.
  3. Grant the bind user delete permission on the target subtree, or bind with an admin/service account.
  4. Delete child entries before deleting a parent, if the directory requires leaf deletion.

Example fix

// before
connection.delete("cn=" + name + ",ou=people,dc=example,dc=com", true);
// after
String safeName = name.replace("\\", "\\\\").replace(",", "\\,");
connection.delete("cn=" + safeName + ",ou=people,dc=example,dc=com", true);
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate DN shape before deleting
javax.naming.ldap.LdapName ln = new javax.naming.ldap.LdapName(dn); // throws InvalidNameException on malformed DN
// and confirm the bind user's delete rights out-of-band (ACI review)

Type guard

boolean isValidDn(String dn) { try { new javax.naming.ldap.LdapName(dn); return true; } catch (InvalidNameException e) { return false; } }

Try / catch

try {
  connection.delete(dn, true);
} catch (KettleException e) {
  Throwable root = ExceptionUtils.getRootCause(e);
  if (root instanceof NoPermissionException) throw new KettleException("Bind user lacks delete rights on " + dn, e);
  if (root instanceof InvalidNameException) throw new KettleException("Malformed DN: " + dn, e);
  throw e;
}

Prevention

When it happens

Trigger: Calling delete() with a malformed DN string, a DN containing unescaped special characters, while bound as a user without delete rights on the entry, or when the server refuses deletion of entries that still have children.

Common situations: DN values from CSV/database fields containing unescaped commas or slashes; bind account lacking ACI/ACL delete permission; attempting to delete a non-leaf entry on directories that forbid it; SSL/TLS handshake failure mid-operation.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/a71c3920d03fe0d4. Report an issue: GitHub.

Appendix: source

Thrown at plugins/ldap/impl/src/main/java/org/pentaho/di/trans/steps/ldapinput/LDAPConnection.java:295

      if ( checkEntry ) {
        // First Check entry
        getInitialContext().lookup( dn );
      }
      // The entry exists
      getInitialContext().destroySubcontext( dn );
      if ( log.isDebug() ) {
        log.logDebug( BaseMessages.getString( PKG, "LDAPinput.Exception.Deleted", dn ) );
      }
      return STATUS_DELETED;
    } catch ( NameNotFoundException n ) {
      // The entry is not found
      if ( checkEntry ) {
        throw new KettleException(
          BaseMessages.getString( PKG, "LDAPConnection.Error.Deleting.NameNotFound", dn ), n );
      }
      return STATUS_SKIPPED;
    } catch ( Exception e ) {
      throw new KettleException( BaseMessages.getString( PKG, "LDAPConnection.Error.Delete", dn ), e );
    }
  }

  public int update( String dn, String[] attributes, String[] values, boolean checkEntry ) throws KettleException {
    try {
      int nrAttributes = attributes.length;
      ModificationItem[] mods = new ModificationItem[nrAttributes];
      for ( int i = 0; i < nrAttributes; i++ ) {
        // Define attribute
        Attribute mod = new BasicAttribute( attributes[i], values[i] );
        if ( log.isDebug() ) {
          log
            .logDebug( BaseMessages.getString( PKG, "LDAPConnection.Update.Attribute", attributes[i], values[i] ) );
        }
        // Save update action on attribute
        mods[i] = new ModificationItem( DirContext.REPLACE_ATTRIBUTE, mod );
      }
      // We have all requested attribute

View on GitHub (pinned to f3058517a1)