{"record":{"id":"44015fdc4b216e6c","repo":"pentaho/pentaho-kettle","slug":"ldapconnection-error-renaming","errorCode":"LDAPConnection.Error.Renaming","errorMessage":"LDAPConnection.Error.Renaming","messagePattern":"LDAPConnection\\.Error\\.Renaming","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"plugins/ldap/impl/src/main/java/org/pentaho/di/trans/steps/ldapinput/LDAPConnection.java","lineNumber":494,"sourceCode":"        // re attached removed sub contexts\n        for ( int i = paths.size(); i > 0; i-- ) {\n          getInitialContext().createSubcontext( paths.get( i - 1 ), childs.get( paths.get( i - 1 ) ) );\n        }\n        throw e;\n      }\n\n      // attach sub context\n      List<String> newpaths = new ArrayList<String>();\n      for ( String childName : paths ) {\n        newpaths.add( childName.replaceAll( oldDn, newDn ) );\n      }\n\n      for ( int i = newpaths.size(); i > 0; i-- ) {\n        getInitialContext().createSubcontext( newpaths.get( i - 1 ), childs.get( paths.get( i - 1 ) ) );\n      }\n\n    } catch ( Exception e ) {\n      throw new KettleException( BaseMessages.getString( PKG, \"LDAPConnection.Error.Renaming\", oldDn, newDn ), e );\n    } finally {\n      try {\n        if ( !deleteRDN ) {\n          // Delete the old dn as attribute\n          // switch back to default value\n          getInitialContext().addToEnvironment( \"java.naming.ldap.deleteRDN\", \"true\" );\n        }\n      } catch ( Exception e ) {\n        // Ignore errors\n      }\n    }\n\n  }\n\n  @SuppressWarnings( \"rawtypes\" )\n  private void getPaths( String rootName, Map<String, Attributes> childs, List<String> paths ) throws Exception {\n    NamingEnumeration ne = getInitialContext().list( rootName );\n    while ( ne.hasMore() ) {","sourceCodeStart":476,"sourceCodeEnd":512,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/plugins/ldap/impl/src/main/java/org/pentaho/di/trans/steps/ldapinput/LDAPConnection.java#L476-L512","documentation":"LDAPConnection.rename(oldDn, newDn, ...) wraps any exception from the JNDI rename/createSubcontext sequence in a KettleException with message key 'LDAPConnection.Error.Renaming' (oldDn and newDn interpolated). It fails when the source DN doesn't exist, the new DN already exists, the new parent is missing, the directory lacks MODDN support, or the bind user lacks modify-RDN/rename permission.","triggerScenarios":"Renaming to a DN that already exists; moving entries across subtrees when the new parent OU doesn't exist or moddn ( ldap rename) is restricted; renaming entries with children on servers that only support leaf renames; the deleteRDN environment handling failing in the finally block.","commonSituations":"Reorganizing an OU structure on AD where the target CN already exists; bind account missing 'Modify RDN'/'Delete Child' rights; renaming on proxies/embedded directories without full moddn support; leftover temporary child entries from a prior failed rename blocking the re-create of subtree children.","solutions":["Read e.getCause(): NameAlreadyBoundException means the new DN exists — choose a unique new DN or delete/move the conflicting entry.","Ensure the target parent OU exists before renaming.","Grant the bind account rename (moddn) and delete rights on both source and target subtrees.","For subtrees, verify no leftover children from a previous failed rename and rename leaves first.","Test the rename manually with ldapmoddn/ldp.exe before running the transformation."],"exampleFix":"// before\nconnection.rename(\"cn=jsmith,ou=people,dc=example,dc=com\", \"cn=smith,ou=people,dc=example,dc=com\", true, false);\n// after (ensure uniqueness of the new RDN first)\nif (!dnExists(connection, \"cn=smith,ou=people,dc=example,dc=com\")) {\n  connection.rename(\"cn=jsmith,ou=people,dc=example,dc=com\", \"cn=smith,ou=people,dc=example,dc=com\", true, false);\n}","handlingStrategy":"try-catch","validationCode":"// Pre-check: source exists and target is free\nboolean sourceExists = dnExists(connection, oldDn);\nboolean targetFree = !dnExists(connection, newDn);\nif (!sourceExists || !targetFree) throw new KettleException(\"Rename pre-check failed for \" + oldDn + \" -> \" + newDn);","typeGuard":null,"tryCatchPattern":"try {\n  connection.rename(oldDn, newDn, true, false);\n} catch (KettleException e) {\n  Throwable root = ExceptionUtils.getRootCause(e);\n  if (root instanceof NameAlreadyBoundException) { /* new DN taken: pick unique RDN or clean up */ }\n  else if (root instanceof OperationNotSupportedException) { /* server lacks moddn/move support */ }\n  else if (root instanceof NoPermissionException) { /* grant moddn/delete rights */ }\n  throw e;\n}","preventionTips":["Uniqueness-check the new DN before renaming","Grant 'Modify RDN'/moddn and delete rights on both subtrees","Handle subtree renames carefully: rename children leaves-first and clean leftovers from failed runs","Verify the directory supports moves across OUs (some proxies/embedded servers do not)"],"tags":["ldap","kettle","rename","moddn"],"backgroundTag":"invalid-state-transition","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"}