pentaho/pentaho-kettle · error · SftpException
Failed to rename from to
Error message
Failed to rename from to
What it means
MinaSftpSession.rename(oldPath, newPath) wraps IOException from client.rename into an SftpException. The rename failed server-side, typically because the source does not exist, the target already exists (SFTP rename usually refuses overwrite), or permissions are insufficient.
Solutions
- Ensure the target does not exist (delete it first) or use a unique temp name for atomic publish
- Verify the source path exists and the target's parent directory exists
- Check modify permissions on both source and target directories
- Retry on transient IO errors after reconnecting the session
Example fix
// before
session.rename("/in/a.csv", "/done/a.csv");
// after
if (session.fileExists("/done/a.csv")) { session.delete("/done/a.csv"); }
session.rename("/in/a.csv", "/done/a.csv"); Defensive patterns
Strategy: validation
Validate before calling
// ensure source exists and target is free before rename
try { session.size(oldPath); } catch (SftpException e) { throw new IllegalStateException("source missing: " + oldPath, e); }
try { session.size(newPath); session.delete(newPath); } catch (SftpException ignored) { /* target absent: fine */ } Type guard
boolean canRename(MinaSftpSession s, String from, String to) {
try { s.size(from); return true; } catch (SftpException e) { return false; }
// plus a target-free check as in validationCode
} Try / catch
try {
session.rename(oldPath, newPath);
} catch (SftpException e) {
if (session.fileExists(newPath)) { session.delete(newPath); session.rename(oldPath, newPath); return; }
throw new IOException("rename " + oldPath + " -> " + newPath + " failed: " + e.getCause(), e);
} Prevention
- Delete or version the target name first; SFTP rename rarely overwrites
- Use unique temp names + rename for atomic publishes to avoid collisions
- Ensure the target directory exists and both paths are within permitted scope
- Watch for case-only renames on case-insensitive servers
When it happens
Trigger: Calling rename(oldPath, newPath) when oldPath is missing, newPath already exists and the server does not allow overwriting rename, source and target on paths the user cannot modify, or a dropped session.
Common situations: Atomic publish patterns (upload temp then rename) breaking when the destination file was created concurrently, case-only renames on case-insensitive servers, moving files across directories where the target dir is missing.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 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/cf06aa02f38e7e30.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/core/ssh/mina/MinaSftpSession.java:142
@Override
public void delete( String path ) throws SftpException {
try {
if ( isDirectory( path ) ) {
client.rmdir( path );
} else {
client.remove( path );
}
} catch ( IOException e ) {
throw new SftpException( "Failed to delete: " + path, e );
}
}
@Override
public void rename( String oldPath, String newPath ) throws SftpException {
try {
client.rename( oldPath, newPath );
} catch ( IOException e ) {
throw new SftpException( "Failed to rename from " + oldPath + " to " + newPath, e );
}
}
@Override
public void close() {
try {
client.close();
} catch ( IOException ignored ) {
// Ignore
}
}
}
View on GitHub (pinned to f3058517a1)