pentaho/pentaho-kettle · error · SftpException

Failed to upload file:

Error message

Failed to upload file: 

What it means

MinaSftpSession.upload() wraps IOException from client.write(...) and the read loop into an SftpException. The remote file could not be created/written or the transfer was interrupted. It also covers permission failures on the remote target directory and quota exhaustion.

Solutions

  1. Verify the target remote directory exists and is writable by the SSH user
  2. Delete or rename an existing remote file before uploading, or pass overwrite=true if supported
  3. Upload to a temp name then rename atomically to avoid partial-file corruption
  4. Retry with backoff on transient network failures and clean up partial uploads

Example fix

// before
session.upload(in, "/data/out.csv", false);
// after
if (session.fileExists("/data/out.csv")) { session.delete("/data/out.csv"); }
try { session.upload(in, "/data/out.csv.tmp", true); session.rename("/data/out.csv.tmp", "/data/out.csv"); }
catch (SftpException e) { throw new IOException("Upload failed: " + e.getCause(), e); }
Defensive patterns

Strategy: try-catch

Validate before calling

String tmp = remote + ".tmp." + System.currentTimeMillis();
try { session.delete(tmp); } catch (SftpException ignored) {}
// verify target dir writable by attempting a probe
try { session.mkdir(remoteDir); } catch (SftpException e) { /* may already exist */ }

Type guard

boolean canUploadTo(MinaSftpSession s, String target) {
  String dir = target.substring(0, target.lastIndexOf('/') + 1);
  try { s.mkdir(dir + ".permcheck"); s.delete(dir + ".permcheck"); return true; }
  catch (SftpException e) { return false; }
}

Try / catch

try {
  session.upload(in, tmpName, true);
  session.rename(tmpName, remote);
} catch (SftpException e) {
  try { session.delete(tmpName); } catch (SftpException ignored) {}
  throw new IOException("upload to " + remote + " failed: " + e.getCause(), e);
}

Prevention

When it happens

Trigger: Calling upload(source, remote, overwrite) with overwrite=false when the remote file exists (server returns failure), remote directory not writable, disk quota exceeded on the server, or connection drop mid-upload.

Common situations: Uploading to a path in a non-writable directory, hitting a server-side file-already-exists policy when overwrite is false, partial uploads left behind after a network blip, or SFTP subsystem limits on file size.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/core/ssh/mina/MinaSftpSession.java:111

  @Override
  public void upload( InputStream source, String remote, boolean overwrite ) throws SftpException {
    try {
      try ( SftpClient.CloseableHandle h = client.open( remote, SftpClient.OpenMode.Write, SftpClient.OpenMode.Create,
        SftpClient.OpenMode.Truncate ) ) {
        byte[] buf = new byte[ 8192 ];
        int r;
        long off = 0;
        while ( ( r = source.read( buf ) ) >= 0 ) {
          if ( r == 0 ) {
            continue;
          }
          client.write( h, off, buf, 0, r );
          off += r;
        }
      }
    } catch ( IOException e ) {
      throw new SftpException( "Failed to upload file: " + remote, e );
    }
  }

  @Override
  public void mkdir( String path ) throws SftpException {
    try {
      client.mkdir( path );
    } catch ( IOException e ) {
      throw new SftpException( "Failed to create directory: " + path, e );
    }
  }

  @Override
  public void delete( String path ) throws SftpException {
    try {
      if ( isDirectory( path ) ) {
        client.rmdir( path );
      } else {

View on GitHub (pinned to f3058517a1)