pentaho/pentaho-kettle · error · FileSystemException
Illegal move target
Error message
Illegal move target
What it means
JCRSolutionFileObject.callRepoMove refuses to move a file when the target folder is null, which happens when the computed destination lies beyond the repository root. It throws a plain FileSystemException('Illegal move target') before any repository call is made. This is a client-side guard against a malformed move destination.
Solutions
- Validate that the target's parent resolves to an existing folder inside the repository before calling moveTo
- Skip or reject moves whose target parent is null (beyond root) instead of attempting them
- Compute the target via another valid FileObject rather than string-manipulating paths
Example fix
// before
FileObject dest = fs.resolveFile( parentPathOf( src ) ); // may be beyond root
src.moveTo( dest );
// after
FileObject dest = fs.resolveFile( parentPathOf( src ) );
if ( dest == null || dest.getParent() == null ) {
throw new IllegalArgumentException( "Move target must be inside the repository" );
}
src.moveTo( dest ); Defensive patterns
Strategy: validation
Validate before calling
// validate before moveTo
boolean isValidMoveTarget( FileObject target ) throws FileSystemException {
if ( target == null ) return false;
FileObject parent = target.getParent();
return parent != null && parent.exists();
} Type guard
FileObject requireInsideRepository( FileObject target ) throws FileSystemException {
FileObject parent = ( target == null ) ? null : target.getParent();
if ( parent == null ) throw new IllegalArgumentException( "Move target must be inside the repository" );
return target;
} Try / catch
try {
src.moveTo( target );
} catch ( FileSystemException e ) {
if ( "Illegal move target".equals( e.getMessage() ) ) {
// reject operation in UI/log instead of crashing
} else { throw e; }
} Prevention
- Never compute move targets by raw string manipulation of repository paths
- Always resolve the destination parent as a FileObject and check it exists
- Reject moves whose destination is at or above the repository root
When it happens
Trigger: Calling fileObject.moveTo(target) where resolving the target's parent yields null — i.e. attempting to move a folder (typically a top-level folder) to a parent above the repository root.
Common situations: Programmatic renames/moves that compute the destination path by stripping a path segment, accidentally producing a root-level or above-root target; UI drag-and-drop moving a top-level folder onto the root.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- GPG.ErrorCheckingGPGFile
- Missing connection configuration
- A connection of type PALO is expected
- A connection of type PALO is expected
- A server socket allocation always has to accompanied by a…
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/fa93da496d8e2033.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/repo-vfs/repo-vfs-ws/src/main/java/org/pentaho/di/plugins/repovfs/ws/vfs/JCRSolutionFileObject.java:353
return Objects.equal( file1.getName().getExtension(), file2.getName().getExtension() );
}
private static String getNameNoExt( FileObject file ) {
return FilenameUtils.removeExtension( file.getName().getBaseName() );
}
/** Rename this file in place */
private void callRepoRename( String newName ) throws RepositoryClientException {
String[] origPath = computeFileNames( getName() );
log.debug( "Optimized rename call" );
repoClient.rename( origPath, newName );
}
/** Move this to a different parent */
private void callRepoMove( FileObject targetFolder ) throws FileSystemException, RepositoryClientException {
if ( targetFolder == null ) {
// beyond root
throw new FileSystemException( "Illegal move target" );
}
if ( !targetFolder.exists() ) {
log.debug( "Creating target folder {} for move", targetFolder.getName() );
targetFolder.createFolder();
}
RepositoryFileDto thisFile = getFileDto();
String[] destPath = computeFileNames( targetFolder.getName() );
log.debug( "Optimized move call" );
repoClient.moveTo( thisFile, destPath );
}
private static boolean haveSameName( FileObject file1, FileObject file2 ) {
return file1.getName().getBaseName().equals( file2.getName().getBaseName() );
}
private static boolean haveSameParent( FileObject file1, FileObject file2 ) throws FileSystemException {
FileObject parent1 = file1.getParent();
FileObject parent2 = file2.getParent();View on GitHub (pinned to f3058517a1)