pentaho/pentaho-kettle · error · KettleException
ProcessFiles.Error.SourceFileNotExist
Error message
ProcessFiles.Error.SourceFileNotExist
What it means
Thrown when the source filename from the row is non-empty but the file it points to does not exist on the filesystem (VFS). Pentaho validates existence with data.sourceFile.exists() before performing copy/move/delete operations.
Solutions
- Verify the file exists at the exact path in the row (check case and whitespace) before running the transformation.
- Ensure any job entry that produces the files (e.g. unzip, download) runs before this transformation and succeeded.
- Use absolute paths or verify the relative path against the PDI working directory.
- Enable 'Create parent folder' is irrelevant here; instead add a 'Check if file exists' job entry or a File Exists step to guard the stream.
- Check network share / mount availability and credentials.
Example fix
// before
FileExists(filename='${INPUT_DIR}/data.txt') -> ProcessFiles
// after (guard dynamically)
FileExists(filenameField='filename') -> FilterRows(exists=true) -> ProcessFiles Defensive patterns
Strategy: validation
Validate before calling
// Pre-check in a User Defined Java Expression or via File Exists step: new java.io.File(sourceFilename).exists()
Type guard
boolean sourceFileReadable(String path) {
return path != null && new java.io.File(path).isFile();
} Try / catch
try {
processRow();
} catch (KettleException e) {
if (e.getMessage().contains("SourceFileNotExist")) {
logError("Source file missing: " + extractPath(e));
// skip row or retry
} else throw e;
} Prevention
- Use absolute paths to avoid working-directory ambiguity
- Guarantee upstream file-producing job entries ran successfully
- Add a 'Check if file exists' job entry or File Exists step guard
- Verify case-sensitive paths on Linux and mounts/credentials on network shares
When it happens
Trigger: data.sourceFile.exists() returns false after KettleVFS.getFileObject(sourceFilename); any operation type (copy/move/delete) on a missing file.
Common situations: File deleted by another process between listing and processing; typo or wrong case in path (case-sensitive Linux); relative path resolved against unexpected working directory; file on unmounted network share; staging files not yet created when transformation runs.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- GetSubFolders.Exception.MissingFiles
- GetSubFolders.Exception.NoAccessibleFiles
- GPLoad.Exception.DirectoryDoesNotExist
- GPLoad.Execption.FileDoesNotExist
- JobSQL.SQLFileNotExist
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/906047f24a29bf24.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/processfiles/ProcessFiles.java:112
if ( meta.simulate ) {
if ( log.isBasic() ) {
logBasic( BaseMessages.getString( PKG, "ProcessFiles.Log.SimulationModeON" ) );
}
}
} // End If first
try {
// get source filename
String sourceFilename = getInputRowMeta().getString( r, data.indexOfSourceFilename );
if ( Utils.isEmpty( sourceFilename ) ) {
logError( BaseMessages.getString( PKG, "ProcessFiles.Error.SourceFileEmpty" ) );
throw new KettleException( BaseMessages.getString( PKG, "ProcessFiles.Error.SourceFileEmpty" ) );
}
data.sourceFile = KettleVFS.getInstance( getTransMeta().getBowl() ).getFileObject( sourceFilename, getTransMeta() );
if ( !data.sourceFile.exists() ) {
logError( BaseMessages.getString( PKG, "ProcessFiles.Error.SourceFileNotExist", sourceFilename ) );
throw new KettleException( BaseMessages.getString(
PKG, "ProcessFiles.Error.SourceFileNotExist", sourceFilename ) );
}
if ( data.sourceFile.getType() != FileType.FILE ) {
logError( BaseMessages.getString( PKG, "ProcessFiles.Error.SourceFileNotFile", sourceFilename ) );
throw new KettleException( BaseMessages.getString(
PKG, "ProcessFiles.Error.SourceFileNotFile", sourceFilename ) );
}
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() ) {View on GitHub (pinned to f3058517a1)