pentaho/pentaho-kettle · error · KettleException

ProcessFiles.Error.SourceFileEmpty

Error message

ProcessFiles.Error.SourceFileEmpty

What it means

Thrown when the value of the source filename field in the current row is null or empty. Pentaho throws it because it cannot resolve a VFS FileObject for an empty path and proceeding would produce misleading downstream failures.

Solutions

  1. Add a 'Filter rows' step before ProcessFiles to drop rows where the source filename field is null or empty.
  2. Fix the upstream step that generates the filename so it always emits a valid path.
  3. Use a 'Value Mapper' or 'If field value is null' step to supply a default filename.
  4. Enable error handling on the ProcessFiles step and route empty-filename rows to a separate stream.

Example fix

// before: passing rows straight into ProcessFiles
ProcessFiles(sourceField='filename')
// after
FilterRows(field='filename', operator='IS NOT NULL AND <> ""') -> ProcessFiles(sourceField='filename')
Defensive patterns

Strategy: validation

Validate before calling

// Filter rows step condition before ProcessFiles:
ISNOTNULL( [sourceFilename] ) && [sourceFilename] <> ""

Type guard

boolean hasSourceFilename(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("SourceFileEmpty")) {
    logError("Row has empty source filename; routing to error stream");
  } else throw e;
}

Prevention

When it happens

Trigger: getInputRowMeta().getString(r, data.indexOfSourceFilename) returns null or "" for some row; Utils.isEmpty(sourceFilename) is true.

Common situations: Upstream source produced null filename for rows outside the expected set; database column with NULL path values; a filter step removed rows but not the empty ones; text file input with missing column values.

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/727a850fa6d95a4e. Report an issue: GitHub.

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/processfiles/ProcessFiles.java:106

          // The field is unreachable !
          throw new KettleException( BaseMessages.getString( PKG, "ProcessFiles.Exception.CouldnotFindField", meta
            .getDynamicTargetFileNameField() ) );
        }
      }

      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 );

View on GitHub (pinned to f3058517a1)