{"record":{"id":"f48c40fb7e17abbb","repo":"apache/seatunnel","slug":"sftp-lstat-failed-for-path","errorCode":null,"errorMessage":"SFTP lstat failed for path=","messagePattern":"SFTP lstat 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":637,"sourceCode":"            this.client = client;\n        }\n\n        @Override\n        public FileStatus getFileStatus(Path path) throws IOException {\n            Path absolute;\n            try {\n                absolute = makeAbsolute(new Path(client.pwd()), path);\n                if (absolute.getParent() == null) {\n                    return SFTPFileSystem.this.getFileStatus(client, absolute);\n                }\n                SftpATTRS attrs = client.lstat(absolute.toUri().getPath());\n                return SFTPFileSystem.this.getFileStatus(\n                        client, absolute.getName(), attrs, absolute.getParent());\n            } catch (SftpException e) {\n                if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {\n                    throw new FileNotFoundException(String.format(E_FILE_NOTFOUND, path));\n                }\n                throw new IOException(\"SFTP lstat failed for path=\" + path, e);\n            }\n        }\n\n        @Override\n        public void list(Path directory, FileStatusConsumer consumer) throws IOException {\n            Path absolute;\n            try {\n                absolute = makeAbsolute(new Path(client.pwd()), directory);\n                client.ls(\n                        absolute.toUri().getPath(),\n                        entry -> {\n                            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) {","sourceCodeStart":619,"sourceCodeEnd":655,"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#L619-L655","documentation":"getFileStatus() throws this IOException when the SFTP lstat call fails with any error other than 'no such file' — e.g. permission denial, connection loss, or a protocol-level error. The original SftpException is chained so the real cause is preserved.","triggerScenarios":"Calling getFileStatus(path) while the SFTP channel has dropped or the server rejects the stat operation (SSH_FX_PERMISSION_DENIED, SSH_FX_FAILURE, connection reset), i.e. any SftpException whose id != SSH_FX_NO_SUCH_FILE.","commonSituations":"Long-running jobs where the SFTP session times out before the stat call; server-side permission restrictions on a directory; transient network failures mid-job.","solutions":["Inspect the chained SftpException cause for the exact SSH error id/reason.","Ensure the SFTP connection pool keeps channels alive or reconnects; retry the stat after reconnection.","Verify the SFTP user has read/execute permission on every component of the path.","Check network/firewall stability between the job and the SFTP server (timeouts, idle disconnects)."],"exampleFix":"// before\nFileStatus st = sftpFs.getFileStatus(path); // may throw on stale channel\n// after\ntry {\n    FileStatus st = sftpFs.getFileStatus(path);\n} catch (IOException e) {\n    if (e.getCause() instanceof SftpException) { reconnectAndRetry(path); }\n    else throw e;\n}","handlingStrategy":"retry","validationCode":"// lstat failures other than missing file are usually transient/connection related\nif (channel == null || !channel.isConnected()) { channel = pool.connect(); }","typeGuard":null,"tryCatchPattern":"try { FileStatus st = sftpFs.getFileStatus(path); }\ncatch (IOException e) {\n    if (!(e instanceof FileNotFoundException) && e.getCause() instanceof SftpException) { retryWithReconnect(path); }\n    else throw e;\n}","preventionTips":["Enable SFTP keep-alive to avoid idle disconnects","Wrap stat calls in bounded retry with backoff","Ensure read/execute permissions on all path components"],"tags":["sftp","io","lstat","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"}