pentaho/pentaho-kettle · error · InvalidFileTypeException

Illegal attempt to create directory under a file

Error message

Illegal attempt to create directory under a file

What it means

LocalFileProvider.createDirectory throws InvalidFileTypeException when the requested parent 'file' is not a Directory instance — i.e. an attempt to create a subfolder underneath a regular file. The provider only supports nesting directories under directories.

Solutions

  1. Verify the parent is a directory before calling createDirectory
  2. Refresh the file tree and retry with the correct parent node
  3. Catch InvalidFileTypeException and surface 'parent must be a folder' to the user

Example fix

// before
provider.createDirectory( bowl, someFile, "newFolder" );
// after
if ( someFile instanceof Directory ) { provider.createDirectory( bowl, someFile, "newFolder" ); }
Defensive patterns

Strategy: type-guard

Validate before calling

if ( !( parent instanceof Directory ) ) {
  throw new InvalidFileTypeException( "Parent must be a directory" );
}

Type guard

boolean canMkdir( File f ) { return f instanceof Directory; }

Try / catch

try { provider.createDirectory( bowl, parent, name ); } catch ( InvalidFileTypeException e ) { showError( "Selected parent is a file, choose a folder" ); }

Prevention

When it happens

Trigger: Calling createDirectory with a LocalFile (non-directory) as parent, e.g. stale UI tree state or a caller passing the wrong node after the filesystem changed on disk.

Common situations: Folder created between listing and the create call (parent is now a file); UI passing the selected file instead of the selected folder; provider misuse from custom code.

Related errors


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

Appendix: source

Thrown at plugins/file-open-save-new/core/src/main/java/org/pentaho/di/plugins/fileopensave/providers/local/LocalFileProvider.java:501

    }
    return LocalDirectory.create( Utils.getParent( file.getParent(), FileSystems.getDefault().getSeparator() ),
            Paths.get( file.getParent() ) );
  }

  public void clearProviderCache() {
    //Any local caches that this provider might use should be cleared here.
  }

  //Should do nothing if the directory already exists, or create any directories that do not exist
  @Override
  public LocalFile createDirectory( Bowl bowl, String parentPath, LocalFile file, String newFolderName )
    throws FileException {
    LocalDirectory newLocalDirectory;
    if ( file instanceof Directory ) {
        newLocalDirectory = LocalDirectory.create( parentPath,
          Paths.get( file.getPath() + FileSystems.getDefault().getSeparator() + newFolderName ) );
    } else {
      throw new InvalidFileTypeException( "Illegal attempt to create directory under a file" );
    }
    try {
      return this.add( bowl, newLocalDirectory, null );
    } catch ( FileExistsException e ) {
      //The file already exists.  Suppress the error
    }
    return newLocalDirectory;
  }

  @Override
  public LocalFile getFile( Bowl bowl, LocalFile file, VariableSpace space ) {
     Paths.get( file.getPath() );
    return null;
  }

  public class LocalFileVisitor extends SimpleFileVisitor<Path> {
    private final OverwriteStatus overwriteStatus;
    private Map<Path, Path> folderTransversedMap = new HashMap<>();

View on GitHub (pinned to f3058517a1)