{"record":{"id":"db15043e021dd6c3","repo":"pentaho/pentaho-kettle","slug":"failed-to-check-if-path-is-directory","errorCode":null,"errorMessage":"Failed to check if path is directory: ","messagePattern":"Failed to check if path is directory: ","errorType":"exception","errorClass":"SftpException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/core/ssh/mina/MinaSftpSession.java","lineNumber":70,"sourceCode":"    }\n  }\n\n  @Override\n  public boolean exists( String path ) throws SftpException {\n    try {\n      client.stat( path );\n      return true;\n    } catch ( IOException e ) {\n      return false;\n    }\n  }\n\n  @Override\n  public boolean isDirectory( String path ) throws SftpException {\n    try {\n      return client.stat( path ).isDirectory();\n    } catch ( IOException e ) {\n      throw new SftpException( \"Failed to check if path is directory: \" + path, e );\n    }\n  }\n\n  @Override\n  public long size( String path ) throws SftpException {\n    try {\n      return client.stat( path ).getSize();\n    } catch ( IOException e ) {\n      throw new SftpException( \"Failed to get file size: \" + path, e );\n    }\n  }\n\n  @Override\n  public void download( String remote, OutputStream target ) throws SftpException {\n    try {\n      try ( InputStream in = client.read( remote ) ) {\n        in.transferTo( target );\n      }","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/core/ssh/mina/MinaSftpSession.java#L52-L88","documentation":"MinaSftpSession.isDirectory() wraps any IOException from the SSH client stat() call into an SftpException. It means the remote path could not be stat'ed, so the library cannot tell whether it is a directory. The underlying cause (auth, network, missing file) is in the wrapped cause.","triggerScenarios":"Calling isDirectory(path) when client.stat(path) throws IOException: path does not exist, permission denied on path, SFTP channel dropped, or server returned an error to the STAT request.","commonSituations":"Typically reached via delete(path) on a remote file that was already removed, a typo in the remote path, an SFTP server that restricts the user to a chroot subdir the path escapes, or a session that died mid-operation.","solutions":["Verify the remote path exists with an explicit stat or listFiles call before checking isDirectory","Check user permissions on the remote path and parent directory","Confirm the SSH/SFTP session is still connected; reconnect if it dropped","Inspect the wrapped cause (e.getCause()) for the real SSH error code (e.g. no-such-file, permission-denied)"],"exampleFix":"// before\nif (session.isDirectory(path)) { session.delete(path); }\n// after\ntry {\n  if (session.fileExists(path) && session.isDirectory(path)) { session.delete(path); }\n} catch (SftpException e) {\n  log.error(\"stat failed for \" + path + \": \" + e.getCause(), e);\n}","handlingStrategy":"try-catch","validationCode":"// Java: pre-check before acting on the path\nboolean exists;\ntry { session.size(path); exists = true; } catch (SftpException e) { exists = false; }\nif (!exists) { return; } // path already gone\n// also: if (session.isConnected()) { ... }","typeGuard":"boolean pathExists(MinaSftpSession s, String p) {\n  try { s.size(p); return true; } catch (SftpException e) { return false; }\n}","tryCatchPattern":"try {\n  if (session.isDirectory(path)) { session.delete(path); }\n} catch (SftpException e) {\n  Throwable cause = e.getCause();\n  if (cause instanceof java.nio.file.NoSuchFileException) { /* already gone, ignore */ }\n  else throw e;\n}","preventionTips":["Always check existence before directory checks/deletes and treat already-deleted as success","Log e.getCause(), not just the message, to see the real SFTP status code","Verify SSH user permissions and chroot layout before deployment","Keep the session alive with keep-alive or reconnect on idle timeouts"],"tags":["sftp","ssh","file-not-found","io"],"backgroundTag":"resource-not-found","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"}