pentaho/pentaho-kettle · error · KettleException
ProcessFiles.Error.TargetFileNotFile
Error message
ProcessFiles.Error.TargetFileNotFile
What it means
Thrown when the target path exists but is not a regular file (e.g. it is a folder). This guard prevents copy/move operations from overwriting an entire folder with a file, which would corrupt the destination directory.
Solutions
- Correct the target filename expression to include the file name, not just the folder (e.g. /out/dir/file.txt instead of /out/dir).
- Remove or rename the conflicting directory at the target path.
- Use step error handling to catch rows whose target collides with a directory and route them elsewhere.
- Compute target path as concat(targetFolder, "/", baseName(source)) so a folder-only value can never occur.
Example fix
// before target = "/data/output/archive" // a directory // after target = "/data/output/archive/" concat basename(sourceFilename)
Defensive patterns
Strategy: validation
Validate before calling
// Guard: target must be a file path, and if it exists it must not be a directory java.io.File t = new java.io.File(targetFilename); boolean safe = !t.exists() || t.isFile();
Type guard
boolean safeTargetPath(String path) {
java.io.File f = (path == null) ? null : new java.io.File(path);
return f != null && (!f.exists() || f.isFile());
} Try / catch
try {
processRow();
} catch (KettleException e) {
if (e.getMessage().contains("TargetFileNotFile")) {
logError("Target points to a directory: " + extractPath(e));
} else throw e;
} Prevention
- Always append the file name to the target folder in your path expression
- Clean stale directories from the target location before runs
- Validate computed target paths with a File Exists/preview step
- Avoid using user-supplied folder paths directly as full target paths
When it happens
Trigger: Operation Copy/Move; data.targetFile.exists() is true and data.targetFile.getType() != FileType.FILE.
Common situations: Target filename computed to a directory path by mistake (e.g. missing filename part in concatenation); user intended to move into a folder but gave the folder as the destination instead of folder + name; leftover directory at target location from previous runs.
Related errors
- ProcessFiles.Error.SourceFileNotFile
- API coding error: please specify the conversion metadata…
- Calculator.Error.NoNameField
- Calculator.Error.UnableFindField
- Calculator.ErrorInStepRunning
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/725210a221325417.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/processfiles/ProcessFiles.java:137
}
String targetFilename = null;
if ( meta.getOperationType() != ProcessFilesMeta.OPERATION_TYPE_DELETE ) {
// get value for target filename
targetFilename = getInputRowMeta().getString( r, data.indexOfTargetFilename );
if ( Utils.isEmpty( targetFilename ) ) {
logError( BaseMessages.getString( PKG, "ProcessFiles.Error.TargetFileEmpty" ) );
throw new KettleException( BaseMessages.getString( PKG, "ProcessFiles.Error.TargetFileEmpty" ) );
}
data.targetFile = KettleVFS.getInstance( getTransMeta().getBowl() ).getFileObject( targetFilename, getTransMeta() );
if ( data.targetFile.exists() ) {
if ( log.isDetailed() ) {
logDetailed( BaseMessages.getString( PKG, "ProcessFiles.Log.TargetFileExists", targetFilename ) );
}
// check if target is really a file otherwise it could overwrite a complete folder by copy or move operations
if ( data.targetFile.getType() != FileType.FILE ) {
logError( BaseMessages.getString( PKG, "ProcessFiles.Error.TargetFileNotFile", targetFilename ) );
throw new KettleException( BaseMessages.getString(
PKG, "ProcessFiles.Error.TargetFileNotFile", targetFilename ) );
}
} else {
// let's check parent folder
FileObject parentFolder = data.targetFile.getParent();
if ( !parentFolder.exists() ) {
if ( !meta.isCreateParentFolder() ) {
throw new KettleException( BaseMessages.getString(
PKG, "ProcessFiles.Error.TargetParentFolderNotExists", parentFolder.toString() ) );
} else {
parentFolder.createFolder();
}
}
if ( parentFolder != null ) {
parentFolder.close();
}
}View on GitHub (pinned to f3058517a1)