pentaho/pentaho-kettle · error · KettleStepException

SFTPPut.Error.CanNotFindFolder

Error message

SFTPPut.Error.CanNotFindFolder

What it means

Thrown when the move-to destination folder (after-FTP move action) does not exist. The step resolves the folder via KettleVFS and calls exists(); if false it aborts with KettleStepException including the folder path. The step does not create missing destination folders.

Solutions

  1. Create the destination folder before running the transformation, or add a step that creates it.
  2. Correct the folder path in the row data or configuration; use environment-substituted absolute paths.
  3. Verify the VFS URI/scheme and credentials for remote folders.
  4. Add an upstream existence check or 'Create a folder' step for robustness.

Example fix

// before
String folder = "/archive/2026/09"; // never created
// after (upstream step or script)
Files.createDirectories(Paths.get("/archive/2026/09"));
Defensive patterns

Strategy: validation

Validate before calling

Path dir = Paths.get(environmentSubstitute(moveToFolder));
if (!Files.isDirectory(dir)) {
  Files.createDirectories(dir); // or fail fast before the transformation runs
}

Try / catch

try {
  transform.execute();
} catch (KettleStepException e) {
  if (e.getMessage().contains("CanNotFindFolder")) {
    log.error("Create the archive folder or fix the path: " + extractPath(e.getMessage()));
  } else { throw e; }
}

Prevention

When it happens

Trigger: After-FTP action is MOVE, the folder string from the row is non-empty, but KettleVFS destinationFolder.exists() returns false (typo, missing directory, wrong protocol/URI, or unreachable network share).

Common situations: Typo in the archive folder path; directory not pre-created on a new environment; VFS URI scheme mismatch (e.g. sftp:// vs file://); relative path resolving against an unexpected base directory; mounted drive unavailable.

Related errors


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/c789d4c0628768fd. Report an issue: GitHub.

Appendix: source

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

        // 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" ) );
          }

          destinationFolder = KettleVFS.getInstance( getTransMeta().getBowl() ).getFileObject( realDestationFolder );

          if ( !destinationFolder.exists() ) {
            // We can not find folder
            throw new KettleStepException( BaseMessages.getString(
              PKG, "SFTPPut.Error.CanNotFindFolder", realDestationFolder ) );
          }
        }
      }

      // move to spool dir ...
      setSFTPDirectory( getInputRowMeta().getString( r, data.indexOfRemoteDirectory ) );

      // Upload a stream
      data.sftpclient.put( inputStream, destinationFilename );

      if ( file != null ) {
        // We successfully uploaded the file
        // what's next ...
        finishTheJob( file, sourceData, destinationFolder );
      }

      putRow( getInputRowMeta(), r ); // copy row to possible alternate rowset(s).

View on GitHub (pinned to f3058517a1)