pentaho/pentaho-kettle · error · KettleException
ZipFile.Error.SourceFileNotFile
Error message
ZipFile.Error.SourceFileNotFile
What it means
Source-file validation in ZipFile.processRow: the configured source file exists but is not a regular file (it is a directory or special file), so it cannot be zipped. This fires after the existence check passed but the type check failed.
Solutions
- Point the source filename field at individual files, not the containing directory.
- Use a 'Get File Names' step with a wildcard filter to enumerate files, then feed each into ZipFile.
- Fix dynamic filename construction so the file name (not just the folder) is included.
- Add a validation step that checks the path is a file before zipping.
Example fix
// before sourceFilename = "/data/exports"; // directory // after sourceFilename = "/data/exports/report.csv"; // actual file
Defensive patterns
Strategy: validation
Validate before calling
// Before zipping, ensure the path is a regular file
File f = new File(sourceFilename);
if (f.exists() && f.isDirectory()) {
throw new IllegalArgumentException("ZipFile source must be a file, not a directory: " + sourceFilename);
} Try / catch
try {
transformation.execute();
} catch (KettleException e) {
if (e.getMessage() != null && e.getMessage().contains("SourceFileNotFile")) {
log.error("ZipFile source path is a directory - point to individual files", e);
} else { throw e; }
} Prevention
- Enumerate files with a 'Get File Names' step before zipping instead of passing folders.
- Keep the file name (not just the directory) in dynamically built paths.
- Add an is-file check step upstream.
When it happens
Trigger: data.sourceFile.exists() is true but data.sourceFile.getType() != FileType.FILE at ZipFile.java:163, i.e., the path resolves to a directory.
Common situations: User pointed the source filename field at a directory expecting the step to zip the whole folder; a glob or prefix match produced a directory path; dynamic filename construction lost the file extension/name portion.
Related errors
- ZipFile.Error.SourceFileNotExist
- ZipFile.Error.TargetParentFolderNotExists
- Can not append to an existing zip file
- GetSubFolders.Exception.MissingFiles
- GetSubFolders.Exception.NoAccessibleFiles
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/a1ec61fcff8142fa.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/zipfile/ZipFile.java:163
log.logError( toString(), BaseMessages.getString( PKG, "ZipFile.Error.SourceFileEmpty" ) );
throw new KettleException( BaseMessages.getString( PKG, "ZipFile.Error.SourceFileEmpty" ) );
}
data.sourceFile = KettleVFS.getInstance( getTransMeta().getBowl() )
.getFileObject( sourceFilename, this );
// Check sourcefile
boolean skip = false;
if ( !data.sourceFile.exists() ) {
log
.logError( toString(), BaseMessages
.getString( PKG, "ZipFile.Error.SourceFileNotExist", sourceFilename ) );
throw new KettleException( BaseMessages
.getString( PKG, "ZipFile.Error.SourceFileNotExist", sourceFilename ) );
} else {
if ( data.sourceFile.getType() != FileType.FILE ) {
log.logError( toString(), BaseMessages
.getString( PKG, "ZipFile.Error.SourceFileNotFile", sourceFilename ) );
throw new KettleException( BaseMessages.getString(
PKG, "ZipFile.Error.SourceFileNotFile", sourceFilename ) );
}
}
// get basefolder
if ( data.indexOfBaseFolder > -1 ) {
data.baseFolder = getInputRowMeta().getString( r, data.indexOfBaseFolder );
}
// get destination folder
String moveToFolder = null;
if ( data.indexOfMoveToFolder > -1 ) {
moveToFolder = getInputRowMeta().getString( r, data.indexOfMoveToFolder );
if ( Utils.isEmpty( moveToFolder ) ) {
throw new KettleException( BaseMessages.getString( PKG, "ZipFile.Error.EmptyMoveToFolder" ) );
}
}
View on GitHub (pinned to f3058517a1)