pentaho/pentaho-kettle · error · IllegalArgumentException

Destination must be a folder / invalid drag-drop source…

Error message

Destination must be a folder / invalid drag-drop source (dynamic message via processErrorMessage)

What it means

ElementDndProcessor.processErrorMessage throws IllegalArgumentException with a dynamic message when a drag-and-drop target is invalid — typically the destination is not a folder ('Destination "..." must be a folder.') or the destination is a child of the source.

Solutions

  1. Drop onto a directory, not a file
  2. Avoid moving a folder into one of its own children
  3. Catch IllegalArgumentException from the DnD handler and show a validation message instead of performing the move

Example fix

// before
processErrorMessage( "Destination \"" + destinationFolder.getPath() + "\" must be a folder." );
// after (caller-side guard)
if ( destinationFolder.getEntityType().isDirectory() ) { processor.move( src, dest ); }
Defensive patterns

Strategy: validation

Validate before calling

if ( !destinationFolder.getEntityType().isDirectory() ) {
  throw new IllegalArgumentException( "Destination must be a folder" );
}
if ( isChildOf( destinationFolder, sourceObjects ) ) {
  throw new IllegalArgumentException( "Destination is child of source" );
}

Try / catch

try { dndProcessor.determineDestinationFolder( source, target ); } catch ( IllegalArgumentException e ) { showValidationError( e.getMessage() ); }

Prevention

When it happens

Trigger: Dragging files onto a destination that is a file rather than a directory (checked in determineDestinationFolder / checkIfDestinationIsChildOfSource), or nesting a folder into its own descendant.

Common situations: Dragging onto a file icon by accident; attempting to move a parent folder into its own subtree in the file-open-save dialog.

Related errors


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

Appendix: source

Thrown at plugins/file-open-save-new/core/src/main/java/org/pentaho/di/plugins/fileopensave/dragdrop/ElementDndProcessor.java:104

  private static File determineDestinationFolder( Element destination, VariableSpace variableSpace ) {
    if ( checkArray( destination.getEntityType(), DESTINATION_BLACKLIST ) ) {
      processErrorMessage( "Invalid destination.  The destination cannot be a " + destination.getEntityType() );
    }
    return destination.convertToFile( variableSpace );
  }

  private static File[] determineSourceObjects( Element[] source, VariableSpace variables ) {
    return Arrays.stream( source ).map( x -> x.convertToFile( variables ) ).filter( Objects::nonNull )
      .toArray( File[]::new );
  }

  private static boolean checkArray( EntityType entityType, EntityType[] array ) {
    return Arrays.stream( array ).filter( x -> entityType.equals( x ) ).findFirst().isPresent();
  }

  private static void processErrorMessage( String errorMessage ) {
    throw new IllegalArgumentException( errorMessage );
  }

  private static void checkIfDestinationIsChildOfSource( File[] sourceObjects, File destinationFolder ) {
    if ( !destinationFolder.getEntityType().isDirectory() ) {
      processErrorMessage( "Destination \"" + destinationFolder.getPath() + "\" must be a folder." );
    }
    for ( File source : sourceObjects ) {
      int sourcePathLength = source.getPath().length();
      if ( destinationFolder.getPath().indexOf( source.getPath() ) == 0 && ( destinationFolder.getPath().length() ==
        sourcePathLength
        || "/\\".indexOf( destinationFolder.getPath().substring( sourcePathLength, sourcePathLength + 1 ) ) != -1 ) ) {
        processErrorMessage(
          "Destination folder \"" + destinationFolder.getPath() + "\" cannot be a sub-folder of source \""
            + source.getPath() + "\".  This can cause infinite looping." );
      }
    }
  }

View on GitHub (pinned to f3058517a1)