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

  1. Verify the file exists at the exact path in the row (check case and whitespace) before running the transformation.
  2. Ensure any job entry that produces the files (e.g. unzip, download) runs before this transformation and succeeded.
  3. Use absolute paths or verify the relative path against the PDI working directory.
  4. 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.
  5. 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

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


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)