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
- Verify the target remote directory exists and is writable by the SSH user
- Delete or rename an existing remote file before uploading, or pass overwrite=true if supported
- Upload to a temp name then rename atomically to avoid partial-file corruption
- 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
- Upload to a temp name then rename to avoid partial files and exists-conflicts
- Verify the remote directory exists and the user has write permission
- Check server disk quota if uploads fail with no obvious cause
- Clean up temp/partial files in a finally block
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
- Failed to check if path is directory:
- Failed to create directory:
- Failed to delete:
- Failed to download file:
- Failed to get file size:
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)