title: Spring sftp - failed to read file; nested exception is 4
body: <p>Every now and then I get the exception pointed out in the title. Does anyone know what exception 4 means or where this is documented? I've looked at questions relating to this and I've learned that there's exception 2 which apparently means "No such file" and exception 3 which is "Permission Denied". However, when I get nested exception is 4, there is no description so I'm not sure what this means. Is it just a generic read time out? This happens very infrequently, and it's difficult to reproduce, as some of our users have no issues at all, while some run into this issue every now and then.</p>
  
  <pre><code>org.springframework.core.NestedIOException: failed to read file /ftadv:D=IBM-037,C=UTF-8/__'MAIN.FRAME.DATASET'; nested exception is 4:
      at org.springframework.integration.sftp.session.SftpSession.readRaw(SftpSession.java:143)
      at org.springframework.integration.file.remote.session.CachingSessionFactory$CachedSession.readRaw(CachingSessionFactory.java:268)
      at org.springframework.integration.file.remote.session.CachingSessionFactory$CachedSession.readRaw(CachingSessionFactory.java:268)
      at com.my.package.FTPService.ftpStoreAuthData(FTPService.java:166)
      at com.my.package.FTPService.ftpStoreNetAuthData(FTPService.java:59)
      at com.my.package.FTPEndpoint.ftpStoreNetAuthData(FTPEndpoint.java:27)
  </code></pre>
  
  <p>Here's my config if it helps.</p>
  
  <pre><code>@Configuration
  class SftpConfiguration {
  
      @Inject
      private Environment env;
  
      SessionFactory&lt;LsEntry&gt; getSftpSessionFactory() {
          DefaultSftpSessionFactory sftpSessionFactory =
                  new DefaultSftpSessionFactory(Boolean.parseBoolean(env.getRequiredProperty("sftp.isSharedSession")));
          sftpSessionFactory.setHost(env.getRequiredProperty("sftp.host"));
          sftpSessionFactory.setPort(Integer.parseInt(env.getRequiredProperty("sftp.port")));
          sftpSessionFactory.setUser(env.getRequiredProperty("sftp.id"));
          sftpSessionFactory.setPrivateKey(new FileSystemResource(env.getRequiredProperty("sftp.keyPath")));
          sftpSessionFactory.setPrivateKeyPassphrase(env.getRequiredProperty("sftp.passphrase"));
          sftpSessionFactory.setTimeout(Integer.parseInt(env.getRequiredProperty("sftp.timeout")));
          sftpSessionFactory.setAllowUnknownKeys(Boolean.parseBoolean(env.getRequiredProperty("sftp.allowUnknownKeys")));
          return new CachingSessionFactory&lt;LsEntry&gt;(sftpSessionFactory);
      }
  
      CachingSessionFactory getCachingSessionFactory(){
          CachingSessionFactory cachingSessionFactory = new CachingSessionFactory(getSftpSessionFactory());
          cachingSessionFactory.setSessionWaitTimeout(Integer.parseInt(env.getRequiredProperty("sftp.sessionWaitTimeout")));
          cachingSessionFactory.setPoolSize(Integer.parseInt(env.getRequiredProperty("sftp.poolSize")));
          return cachingSessionFactory;
      }
  }
  </code></pre>
  
  <p>And here's an example of the calling code:</p>
  
  <pre><code>@Service
  class FTPService {
      private static final org.apache.logging.log4j.Logger logger = LogManager.getLogger(FTPEndpoint.class);
  
      private CachingSessionFactory cachingSessionFactory;
      private String adviceString;
  
      @Inject
      private FTPService(SftpConfiguration sftpConfig) {
          this.cachingSessionFactory = sftpConfig.getCachingSessionFactory();
          this.adviceString = sftpConfig.getAdviceString();
      }
  
      private String ftpStoreAuthData() {
          Session session = this.cachingSessionFactory.getSession();
          String mainframeDataSet = "'MAIN.FRAME.DATASET'";
  
          try(BufferedInputStream inputStream =  new BufferedInputStream(session.readRaw(adviceString + mainframeDataSet));
              BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))
          {
               Stream&lt;String&gt; lines = reader.lines());
               return doThingsWithFTPData(lines);
          } catch (IOException ex) {
              LogException.writeToFile(ex.getMessage(),ex.getStackTrace(), env.getProperty("sftp.exceptionsPath"));
          }finally {
              try {
                  if (session.isOpen()) {
                      session.finalizeRaw();
                      session.close();
                  }
              }catch (IOException ioe){
                  System.out.println(ioe.getLocalizedMessage() + ioe.getCause().toString());
                  LogException.writeToFile(ioe.getMessage(),ioe.getStackTrace(), env.getProperty("sftp.exceptionsPath"));
                  throw new IOException();
              }
          }
          return "test";
      }
  }
  </code></pre>