pentaho/pentaho-kettle · error · KettleStepException

SFTPPut.Error.CanNotFindField

Error message

SFTPPut.Error.CanNotFindField

What it means

Thrown when the source file path resolved from the row does not exist on the local/VFS filesystem. SFTPPut resolves the path via KettleVFS and calls file.exists(); if false it aborts the row with this KettleStepException, including the path in the message. It prevents attempting to open a stream on a non-existent file.

Solutions

  1. Check the path in the error message and confirm the file exists at that exact location at run time.
  2. Fix variables/relative paths (e.g. use ${Internal.Transformation.Filename.Directory}) so the absolute path is correct.
  3. Ensure the upstream step that writes the file completes before SFTPPut runs (proper hop ordering).
  4. Add an upstream 'Check if file exists' / Filter step to handle missing files gracefully.

Example fix

// before
String path = "/data/${TODAY}/export.csv"; // variable not substituted
// after
String path = environmentSubstitute("${DATA_DIR}/export.csv"); // resolves to existing file
Defensive patterns

Strategy: validation

Validate before calling

File f = new File(environmentSubstitute(sourcePath));
if (f == null || !f.exists()) {
  throw new FileNotFoundException("Source file missing before SFTPPut: " + sourcePath);
}

Try / catch

try {
  transform.execute();
} catch (KettleStepException e) {
  if (e.getMessage().contains("CanNotFindField") && e.getMessage().contains(path)) {
    log.error("Source file does not exist: " + path);
    // route row to an error/retry path
  } else { throw e; }
}

Prevention

When it happens

Trigger: processRow reads sourceData (a file path string) from the row, KettleVFS.getFileObject(sourceData) succeeds but file.exists() returns false.

Common situations: Upstream step generated a filename that was never written; wrong working directory or relative path; file deleted or moved between steps; variable/environment substitution resolving to an unexpected location; permission issues making existence checks fail.

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/1e3f914d00dcd11c. Report an issue: GitHub.

Appendix: source

Thrown at plugins/sftpput/impl/src/main/java/org/pentaho/di/trans/steps/sftpput/SFTPPut.java:179

      if ( meta.isInputStream() ) {
        // Source data is a stream
        inputStream = new ByteArrayInputStream( getInputRowMeta().getBinary( r, data.indexOfSourceFileFieldName ) );

        if ( data.indexOfRemoteFilename == -1 ) {
          // for the case when put data is transferred via input field
          // it is mandatory to specify remote file name
          throw new KettleStepException( BaseMessages.getString( PKG, "SFTPPut.Error.RemoteFilenameFieldMissing" ) );
        }
        destinationFilename = getInputRowMeta().getString( r, data.indexOfRemoteFilename );
      } else {
        // source data is a file
        // let's check file
        file = KettleVFS.getInstance( getTransMeta().getBowl() ).getFileObject( sourceData );

        if ( !file.exists() ) {
          // We can not find file
          throw new KettleStepException( BaseMessages.getString( PKG, "SFTPPut.Error.CanNotFindField", sourceData ) );
        }
        // get stream from file
        inputStream = KettleVFS.getInputStream( file );

        // Destination filename
        destinationFilename = file.getName().getBaseName();
      }

      if ( file != null ) {
        if ( meta.getAfterFTPS() == JobEntrySFTPPUT.AFTER_FTPSPUT_MOVE ) {
          String realDestationFolder = getInputRowMeta().getString( r, data.indexOfMoveToFolderFieldName );

          if ( Utils.isEmpty( realDestationFolder ) ) {
            // Move to destination folder is empty
            throw new KettleStepException( BaseMessages.getString(
              PKG, "SFTPPut.Error.MoveToDestinationFolderIsEmpty" ) );
          }

View on GitHub (pinned to f3058517a1)