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

  1. Set the 'Target filename fieldname' in ProcessFiles to the correct non-empty field.
  2. Fix upstream logic so the target path is always computed (e.g. concatenate target folder + filename with a proper default).
  3. Filter out rows with empty target filename before the step.
  4. 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

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


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)