pentaho/pentaho-kettle · error · KettleException
ProcessFiles.Error.TargetFileEmpty
Error message
ProcessFiles.Error.TargetFileEmpty
What it means
Thrown when operation type is not Delete and the target filename field value in the row is null or empty. The step cannot compute the destination of the copy/move without a target path, so it fails the row.
Solutions
- Set the 'Target filename fieldname' in ProcessFiles to the correct non-empty field.
- Fix upstream logic so the target path is always computed (e.g. concatenate target folder + filename with a proper default).
- Filter out rows with empty target filename before the step.
- Use error handling on the step to divert problematic rows.
Example fix
// before target = concat(targetDir, nullFilename) // yields null/empty // after target = concat(coalesce(targetDir, "/default/out/"), filename)
Defensive patterns
Strategy: validation
Validate before calling
// Filter rows condition before ProcessFiles: ISNOTNULL( [targetFilename] ) && [targetFilename] <> ""
Type guard
boolean hasTargetFilename(Object[] row, RowMetaInterface meta, String field) {
int i = meta.indexOfValue(field);
return i >= 0 && row[i] != null && !row[i].toString().trim().isEmpty();
} Try / catch
try {
processRow();
} catch (KettleException e) {
if (e.getMessage().contains("TargetFileEmpty")) {
logError("Empty target filename; skipping row");
} else throw e;
} Prevention
- Ensure the target filename expression always yields a value (COALESCE/default)
- Verify the configured target field name matches the actual row field
- Filter rows with empty targets before the step
- Enable step error handling for graceful row-level recovery
When it happens
Trigger: Operation is Copy or Move and getInputRowMeta().getString(r, data.indexOfTargetFilename) yields null/"".
Common situations: Target filename field not populated by upstream step; null produced for some rows (e.g. computed filename expression returned null); field name configured points to the wrong column; renamed field in upstream mapping not propagated.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- ProcessFiles.Error.SourceFileEmpty
- ProcessFiles.Error.SourceFileNotFile
- WebServiceAvailable.Error.URLEmpty
- API coding error: please specify the conversion metadata…
- Calculator.Error.NoNameField
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/d79abf996e763dd0.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/processfiles/ProcessFiles.java:127
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() ) {
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() ) {View on GitHub (pinned to f3058517a1)