{"record":{"id":"6e87d7f603bbdf84","repo":"pentaho/pentaho-kettle","slug":"failed-to-upload-file","errorCode":null,"errorMessage":"Failed to upload file: ","messagePattern":"Failed to upload file: ","errorType":"exception","errorClass":"SftpException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/core/ssh/mina/MinaSftpSession.java","lineNumber":111,"sourceCode":"\n  @Override\n  public void upload( InputStream source, String remote, boolean overwrite ) throws SftpException {\n    try {\n      try ( SftpClient.CloseableHandle h = client.open( remote, SftpClient.OpenMode.Write, SftpClient.OpenMode.Create,\n        SftpClient.OpenMode.Truncate ) ) {\n        byte[] buf = new byte[ 8192 ];\n        int r;\n        long off = 0;\n        while ( ( r = source.read( buf ) ) >= 0 ) {\n          if ( r == 0 ) {\n            continue;\n          }\n          client.write( h, off, buf, 0, r );\n          off += r;\n        }\n      }\n    } catch ( IOException e ) {\n      throw new SftpException( \"Failed to upload file: \" + remote, e );\n    }\n  }\n\n  @Override\n  public void mkdir( String path ) throws SftpException {\n    try {\n      client.mkdir( path );\n    } catch ( IOException e ) {\n      throw new SftpException( \"Failed to create directory: \" + path, e );\n    }\n  }\n\n  @Override\n  public void delete( String path ) throws SftpException {\n    try {\n      if ( isDirectory( path ) ) {\n        client.rmdir( path );\n      } else {","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/core/ssh/mina/MinaSftpSession.java#L93-L129","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nsession.upload(in, \"/data/out.csv\", false);\n// after\nif (session.fileExists(\"/data/out.csv\")) { session.delete(\"/data/out.csv\"); }\ntry { session.upload(in, \"/data/out.csv.tmp\", true); session.rename(\"/data/out.csv.tmp\", \"/data/out.csv\"); }\ncatch (SftpException e) { throw new IOException(\"Upload failed: \" + e.getCause(), e); }","handlingStrategy":"try-catch","validationCode":"String tmp = remote + \".tmp.\" + System.currentTimeMillis();\ntry { session.delete(tmp); } catch (SftpException ignored) {}\n// verify target dir writable by attempting a probe\ntry { session.mkdir(remoteDir); } catch (SftpException e) { /* may already exist */ }","typeGuard":"boolean canUploadTo(MinaSftpSession s, String target) {\n  String dir = target.substring(0, target.lastIndexOf('/') + 1);\n  try { s.mkdir(dir + \".permcheck\"); s.delete(dir + \".permcheck\"); return true; }\n  catch (SftpException e) { return false; }\n}","tryCatchPattern":"try {\n  session.upload(in, tmpName, true);\n  session.rename(tmpName, remote);\n} catch (SftpException e) {\n  try { session.delete(tmpName); } catch (SftpException ignored) {}\n  throw new IOException(\"upload to \" + remote + \" failed: \" + e.getCause(), e);\n}","preventionTips":["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"],"tags":["sftp","ssh","upload","permission-denied","io"],"backgroundTag":"file-write-failed","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}