Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Getting 'SSH_FX_NO_SUCH_PATH' SFTP error, even though file exists #9114

Closed
cassis163 opened this issue May 4, 2024 · 3 comments
Closed

Getting 'SSH_FX_NO_SUCH_PATH' SFTP error, even though file exists #9114

cassis163 opened this issue May 4, 2024 · 3 comments

Comments

@cassis163
Copy link

In what version(s) of Spring Integration are you seeing this issue?

6.2.4

Describe the bug
During the development of a custom backup advice, I encountered the 'SSH_FX_NO_SUCH_PATH' SFTP error. The strange thing is that when I connect to the SFTP-server locally, it works fine. But it malfunctions when my Spring Boot project runs inside of a Linux Docker container. Yes, it is a classic 'it works on my machine' type of problem, but after quite a bit of debugging, I still have not found the issue.

The path used for checking if the file exists and eventually for its retrieval is to_wms/orders/15408213_Canonical.json. Prepending this path with '/' is something that I have also tried.

Honestly, I'm not sure if this is actually a bug. It might very well be misconfiguration on my part.

Here are some things that I have tried, but to no avail:

  • Prepending the path with '/'
  • Not prepending the path with '/'
  • Reading the file raw, by retrieving the input stream of the file with session.readRaw
  • Setting the SftpRemoteFileTemplate's remoteDirectory to '/'

This is my backup method:

private void backupFile(SftpRemoteFileInfoDto remoteFileInfo, boolean isSuccess) {
        var filePath = getFilePath(remoteFileInfo);
        if (remoteFileTemplate.exists(filePath)) {
            remoteFileTemplate.get(filePath,
                    inputStream -> createAndSendBackupFile(inputStream, remoteFileInfo, isSuccess));
        } else {
            throw new FileBackupException("File {} does not exist");
        }
    }

Here is the stack trace:

org.springframework.messaging.MessagingException: Failed to execute on session
at org.springframework.integration.file.remote.RemoteFileTemplate.execute(RemoteFileTemplate.java:461)
at org.springframework.integration.file.remote.RemoteFileTemplate.exists(RemoteFileTemplate.java:374)
at nl.omoda.oilcommunicationservice.messaging.oilsftp.advice.BackupAndRemoveAdvice.backupFile(BackupAndRemoveAdvice.java:146)
at nl.omoda.oilcommunicationservice.messaging.oilsftp.advice.BackupAndRemoveAdvice.onAfterInvocation(BackupAndRemoveAdvice.java:96)
at nl.omoda.oilcommunicationservice.messaging.oilsftp.advice.BackupAndRemoveAdvice.tryToExecuteAfterInvocation(BackupAndRemoveAdvice.java:112)
at nl.omoda.oilcommunicationservice.messaging.oilsftp.advice.BackupAndRemoveAdvice.doInvoke(BackupAndRemoveAdvice.java:82)
at org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice.invoke(AbstractRequestHandlerAdvice.java:67)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:223)
at jdk.proxy2/jdk.proxy2.$Proxy230.handleRequestMessage(Unknown Source)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.doInvokeAdvisedRequestHandler(AbstractReplyProducingMessageHandler.java:164)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:148)
at org.springframework.integration.handler.AbstractMessageHandler.doHandleMessage(AbstractMessageHandler.java:105)
at org.springframework.integration.handler.AbstractMessageHandler.handleWithMetrics(AbstractMessageHandler.java:90)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:70)
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:132)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:133)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:106)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:72)
at org.springframework.integration.channel.AbstractMessageChannel.sendInternal(AbstractMessageChannel.java:378)
at org.springframework.integration.channel.AbstractMessageChannel.sendWithMetrics(AbstractMessageChannel.java:349)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:329)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:187)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:166)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:47)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:109)
at org.springframework.integration.handler.AbstractMessageProducingHandler.sendOutput(AbstractMessageProducingHandler.java:501)
at org.springframework.integration.handler.AbstractMessageProducingHandler.doProduceOutput(AbstractMessageProducingHandler.java:356)
at org.springframework.integration.handler.AbstractMessageProducingHandler.produceOutput(AbstractMessageProducingHandler.java:285)
at org.springframework.integration.handler.AbstractMessageProducingHandler.sendOutputs(AbstractMessageProducingHandler.java:249)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:151)
at org.springframework.integration.handler.AbstractMessageHandler.doHandleMessage(AbstractMessageHandler.java:105)
at org.springframework.integration.handler.AbstractMessageHandler.handleWithMetrics(AbstractMessageHandler.java:90)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:70)
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:132)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:133)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:106)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:72)
at org.springframework.integration.channel.AbstractMessageChannel.sendInternal(AbstractMessageChannel.java:378)
at org.springframework.integration.channel.AbstractMessageChannel.sendWithMetrics(AbstractMessageChannel.java:349)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:329)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:302)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:187)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:166)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:47)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:109)
at org.springframework.integration.endpoint.SourcePollingChannelAdapter.handleMessage(SourcePollingChannelAdapter.java:206)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.messageReceived(AbstractPollingEndpoint.java:481)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.doPoll(AbstractPollingEndpoint.java:467)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.pollForMessage(AbstractPollingEndpoint.java:419)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.lambda$createPoller$4(AbstractPollingEndpoint.java:355)
at org.springframework.integration.util.ErrorHandlingTaskExecutor.lambda$execute$0(ErrorHandlingTaskExecutor.java:57)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50)
at org.springframework.integration.util.ErrorHandlingTaskExecutor.execute(ErrorHandlingTaskExecutor.java:55)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.lambda$createPoller$5(AbstractPollingEndpoint.java:348)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:96)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:840)
Caused by: java.io.UncheckedIOException: Cannot check 'lstat' for path to_wms/orders/15408213_Canonical.json
at org.springframework.integration.sftp.session.SftpSession.exists(SftpSession.java:199)
at org.springframework.integration.file.remote.session.CachingSessionFactory$CachedSession.exists(CachingSessionFactory.java:286)
at org.springframework.integration.file.remote.RemoteFileTemplate.lambda$exists$1(RemoteFileTemplate.java:374)
at org.springframework.integration.file.remote.RemoteFileTemplate.execute(RemoteFileTemplate.java:452)
... 62 more
Caused by: SFTP error (SSH_FX_NO_SUCH_PATH): The file path does not exist or is invalid.
at org.apache.sshd.sftp.client.impl.AbstractSftpClient.throwStatusException(AbstractSftpClient.java:277)
at org.apache.sshd.sftp.client.impl.AbstractSftpClient.checkAttributesResponse(AbstractSftpClient.java:333)
at org.apache.sshd.sftp.client.impl.AbstractSftpClient.checkAttributes(AbstractSftpClient.java:325)
at org.apache.sshd.sftp.client.impl.AbstractSftpClient.lstat(AbstractSftpClient.java:1010)
at org.springframework.integration.sftp.session.SftpSession.exists(SftpSession.java:191)
... 65 more

To Reproduce

Use the SftpRemoteFileTemplate inside of an advice in a Linux Docker container and try to call either the exists or get method.

Expected behavior

The file should be retrieved succesfully.

@cassis163 cassis163 added status: waiting-for-triage The issue need to be evaluated and its future decided type: bug labels May 4, 2024
@artembilan
Copy link
Member

Caused by: java.io.UncheckedIOException: Cannot check 'lstat' for path to_wms/orders/15408213_Canonical.json

Maybe there is supposed to be some permission enabled for such a command?

@artembilan
Copy link
Member

@cassis163 ,

Please, take a look here: #9123.
Sounds like similar problem to yours when you try to remoteFileTemplate.get().

@artembilan
Copy link
Member

Caused by: SFTP error (SSH_FX_NO_SUCH_PATH): The file path does not exist or is invalid.
at org.apache.sshd.sftp.client.impl.AbstractSftpClient.throwStatusException(AbstractSftpClient.java:277)
at org.apache.sshd.sftp.client.impl.AbstractSftpClient.checkAttributesResponse(AbstractSftpClient.java:333)
at org.apache.sshd.sftp.client.impl.AbstractSftpClient.checkAttributes(AbstractSftpClient.java:325)
at org.apache.sshd.sftp.client.impl.AbstractSftpClient.lstat(AbstractSftpClient.java:1010)
at org.springframework.integration.sftp.session.SftpSession.exists(SftpSession.java:191)

Looks like this one has to use a canonicaPath() as well.

Will fix it shortly.

@artembilan artembilan added this to the 6.3.0 milestone May 7, 2024
spring-builds pushed a commit that referenced this issue May 7, 2024
Fixes: #9114

If path is not in normalized presentation, the SFTP operation might fail like:
```
Caused by: SFTP error (SSH_FX_NO_SUCH_PATH): The file path does not exist or is invalid.
at org.apache.sshd.sftp.client.impl.AbstractSftpClient.throwStatusException(AbstractSftpClient.java:277)
at org.apache.sshd.sftp.client.impl.AbstractSftpClient.checkAttributesResponse(AbstractSftpClient.java:333)
at org.apache.sshd.sftp.client.impl.AbstractSftpClient.checkAttributes(AbstractSftpClient.java:325)
at org.apache.sshd.sftp.client.impl.AbstractSftpClient.lstat(AbstractSftpClient.java:1010)
at org.springframework.integration.sftp.session.SftpSession.exists(SftpSession.java:191)
```

* Use it now like this `this.sftpClient.lstat(normalizePath(path))`

(cherry picked from commit 8b88668)
spring-builds pushed a commit that referenced this issue May 7, 2024
Fixes: #9114

If path is not in normalized presentation, the SFTP operation might fail like:
```
Caused by: SFTP error (SSH_FX_NO_SUCH_PATH): The file path does not exist or is invalid.
at org.apache.sshd.sftp.client.impl.AbstractSftpClient.throwStatusException(AbstractSftpClient.java:277)
at org.apache.sshd.sftp.client.impl.AbstractSftpClient.checkAttributesResponse(AbstractSftpClient.java:333)
at org.apache.sshd.sftp.client.impl.AbstractSftpClient.checkAttributes(AbstractSftpClient.java:325)
at org.apache.sshd.sftp.client.impl.AbstractSftpClient.lstat(AbstractSftpClient.java:1010)
at org.springframework.integration.sftp.session.SftpSession.exists(SftpSession.java:191)
```

* Use it now like this `this.sftpClient.lstat(normalizePath(path))`

(cherry picked from commit 8b88668)
EddieChoCho pushed a commit to EddieChoCho/spring-integration that referenced this issue Jun 26, 2024
Fixes: spring-projects#9114

If path is not in normalized presentation, the SFTP operation might fail like:
```
Caused by: SFTP error (SSH_FX_NO_SUCH_PATH): The file path does not exist or is invalid.
at org.apache.sshd.sftp.client.impl.AbstractSftpClient.throwStatusException(AbstractSftpClient.java:277)
at org.apache.sshd.sftp.client.impl.AbstractSftpClient.checkAttributesResponse(AbstractSftpClient.java:333)
at org.apache.sshd.sftp.client.impl.AbstractSftpClient.checkAttributes(AbstractSftpClient.java:325)
at org.apache.sshd.sftp.client.impl.AbstractSftpClient.lstat(AbstractSftpClient.java:1010)
at org.springframework.integration.sftp.session.SftpSession.exists(SftpSession.java:191)
```

* Use it now like this `this.sftpClient.lstat(normalizePath(path))`

**Auto-cherry-pick to `6.2.x` & `6.1.x`**
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants