{"record":{"id":"d72dcf0a32eb1cf4","repo":"pentaho/pentaho-kettle","slug":"failed-to-copy-directory-into-itself","errorCode":null,"errorMessage":"Failed to copy directory into itself","messagePattern":"Failed to copy directory into itself","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/repository/kdr/delegates/KettleDatabaseRepositoryDirectoryDelegate.java","lineNumber":214,"sourceCode":"    }\n    repository.directoryDelegate.deleteDirectory( dir.getObjectId() );\n  }\n\n  /**\n   * Move / rename a directory in the repository\n   *\n   * @param id_directory\n   *          Id of the directory to be moved/renamed\n   * @param id_directory_parent\n   *          Id of the new parent directory (null if the parent does not change)\n   * @param newName\n   *          New name for this directory (null if the name does not change)\n   * @throws KettleException\n   */\n  public synchronized void renameDirectory( ObjectId id_directory, ObjectId id_directory_parent, String newName ) throws KettleException {\n    if ( id_directory.equals( id_directory_parent ) ) {\n      // Make sure the directory cannot become its own parent\n      throw new KettleException( \"Failed to copy directory into itself\" );\n    } else {\n      // Make sure the directory does not become a descendant of itself\n      RepositoryDirectory rd = new RepositoryDirectory();\n      loadRepositoryDirectory( rd, id_directory );\n      if ( rd.findDirectory( id_directory_parent ) != null ) {\n        // The parent directory is a child of this directory. Do not proceed\n        throw new KettleException( \"Directory cannot become a child to itself\" );\n      } else {\n        // Check for duplication\n        RepositoryDirectory newParent = new RepositoryDirectory();\n        loadRepositoryDirectory( newParent, id_directory_parent );\n        RepositoryDirectory child = newParent.findChild( newName == null ? rd.getName() : newName );\n        if ( child != null ) {\n          throw new KettleException( \"Destination directory already contains a diectory with requested name\" );\n        }\n      }\n    }\n","sourceCodeStart":196,"sourceCodeEnd":232,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/repository/kdr/delegates/KettleDatabaseRepositoryDirectoryDelegate.java#L196-L232","documentation":"Thrown by renameDirectory when id_directory equals id_directory_parent, i.e. a rename/move is requested that would make a directory its own parent. The library explicitly blocks this because a directory cannot contain itself. It is a pre-validation guard, thrown before any database write.","triggerScenarios":"Calling repository.renameRepositoryDirectory(id, newParentDir, newName) where newParentDir is the directory being moved itself, or calling the delegate's renameDirectory(id, id, name) directly with identical ObjectIds.","commonSituations":"UI drag-and-drop mishandled so a folder is dropped onto itself; code that computes the target parent from the same variable used for the source; off-by-one in tree navigation passing the same node as parent.","solutions":["Check that the new parent directory is not the directory being moved before calling the API","Compare ObjectIds: if id_directory.equals(id_directory_parent), abort or pick a different parent","In UI code, disable dropping a node onto itself","Ensure RepositoryDirectory.getObjectId() is set (null-vs-set confusion can lead to wrong comparisons)"],"exampleFix":"// before\nrepository.renameRepositoryDirectory( dirId, repo.findDirectory( \"/a/b\" ), null ); // if /a/b IS dirId -> throws\n// after\nRepositoryDirectoryInterface parent = repo.findDirectory( \"/a/b\" );\nif ( !parent.getObjectId().equals( dirId ) ) {\n  repository.renameRepositoryDirectory( dirId, parent, null );\n}","handlingStrategy":"validation","validationCode":"if ( id_directory.equals( id_directory_parent ) ) {\n  throw new IllegalArgumentException( \"Target parent must differ from the directory being moved\" );\n}","typeGuard":"boolean isValidMoveTarget( ObjectId sourceId, RepositoryDirectoryInterface newParent ) {\n  return newParent != null && !newParent.getObjectId().equals( sourceId );\n}","tryCatchPattern":null,"preventionTips":["Compare ObjectIds of source and new parent before any move","In UI code, disable dropping a node onto itself","Compute parent directories from distinct variables to avoid self-assignment","Set ObjectIds explicitly before comparisons to avoid null/sentinel mismatches"],"tags":["validation","directory-move","self-reference"],"backgroundTag":"invalid-argument-value","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"}