{"record":{"id":"9006e668802cfc45","repo":"apache/seatunnel","slug":"sftp-readdir-failed-for-path","errorCode":null,"errorMessage":"SFTP READDIR failed for path=","messagePattern":"SFTP READDIR failed for path=","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-file/connector-file-sftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/system/SFTPFileSystem.java","lineNumber":667,"sourceCode":"                            String name = entry.getFilename();\n                            if (!\".\".equals(name) && !\"..\".equals(name)) {\n                                try {\n                                    consumer.accept(\n                                            SFTPFileSystem.this.getFileStatus(\n                                                    client, entry, absolute));\n                                } catch (IOException e) {\n                                    throw new ListingRuntimeException(e);\n                                }\n                            }\n                            return LsEntrySelector.CONTINUE;\n                        });\n            } catch (ListingRuntimeException e) {\n                throw e.ioException;\n            } catch (SftpException e) {\n                if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {\n                    throw new FileNotFoundException(String.format(E_FILE_NOTFOUND, directory));\n                }\n                throw new IOException(\"SFTP READDIR failed for path=\" + directory, e);\n            }\n        }\n\n        @Override\n        public void close() throws IOException {\n            disconnect(client);\n        }\n    }\n\n    private static final class ListingRuntimeException extends RuntimeException {\n        private final IOException ioException;\n\n        private ListingRuntimeException(IOException ioException) {\n            super(ioException);\n            this.ioException = ioException;\n        }\n    }\n","sourceCodeStart":649,"sourceCodeEnd":685,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-file/connector-file-sftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/system/SFTPFileSystem.java#L649-L685","documentation":"Thrown by the SFTP list operator when the READDIR (ls) call fails with an error other than 'no such file' — permission denial, connection loss, or other protocol errors. The original SftpException is attached as the cause.","triggerScenarios":"Calling list()/listFiles on an SFTP directory while the channel is broken or the server denies the READDIR (SSH_FX_PERMISSION_DENIED, SSH_FX_FAILURE), i.e. any SftpException whose id != SSH_FX_NO_SUCH_FILE.","commonSituations":"Idle SFTP connection dropped by server/firewall before the listing; directory unreadable by the SFTP account; server-side failures during large directory scans.","solutions":["Inspect the chained SftpException cause for the exact SSH error id.","Re-establish the SFTP connection (connection pool reconnect) and retry the listing.","Grant the SFTP user read permission on the directory.","Increase/verify keep-alive and timeout settings to avoid mid-operation disconnects."],"exampleFix":"// before\nList<FileStatus> fs = list(dir); // throws on stale channel\n// after\ntry { List<FileStatus> fs = list(dir); }\ncatch (IOException e) { if (isConnectionError(e)) { reconnect(); list(dir); } else throw e; }","handlingStrategy":"retry","validationCode":"if (channel == null || !channel.isConnected()) { channel = pool.connect(); }","typeGuard":null,"tryCatchPattern":"try { files = listFiles(dir); }\ncatch (IOException e) {\n    if (!(e instanceof FileNotFoundException)) { reconnect(); files = listFiles(dir); }\n    else throw e;\n}","preventionTips":["Use bounded retries with backoff for directory scans","Keep SFTP sessions alive during long scans","Grant the SFTP account read permission on scanned directories"],"tags":["sftp","io","readdir","connection"],"backgroundTag":"http-request-failed","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}