Skip to content

Ivy Install task fails with JSCH SFTP error 4 first time, but is successful on subsequent attempts

I am trying to use the ANT Ivy install task to copy a library from one repository to the other.

Some example code within my ANT target:

<ivy:install organisation="testOrg" module="testModuleName" revision="1.2.3" from="fromRepo" to="toRepo"/>

The fromRepo and toRepo are defined in a local ivysettings.xml file.

The resolve (from fromRepo) of the library is successful but the install to toRepo fails, with an SFTP Code 4 error.

impossible to install testOrg#testModuleName;1.2.3: java.io.IOException: Failure
        at org.apache.ivy.plugins.repository.sftp.SFTPRepository.put(SFTPRepository.java:164)
        at org.apache.ivy.plugins.repository.AbstractRepository.put(AbstractRepository.java:130)
        at org.apache.ivy.plugins.resolver.RepositoryResolver.put(RepositoryResolver.java:234)
        at org.apache.ivy.plugins.resolver.RepositoryResolver.publish(RepositoryResolver.java:215)
        at org.apache.ivy.core.install.InstallEngine.install(InstallEngine.java:150)
        at org.apache.ivy.Ivy.install(Ivy.java:537)
        at org.apache.ivy.ant.IvyInstall.doExecute(IvyInstall.java:102)
        at org.apache.ivy.ant.IvyTask.execute(IvyTask.java:271)
...
Caused by: 4: Failure
        at com.jcraft.jsch.ChannelSftp.throwStatusError(ChannelSftp.java:2833)
        at com.jcraft.jsch.ChannelSftp.mkdir(ChannelSftp.java:2142)
        at org.apache.ivy.plugins.repository.sftp.SFTPRepository.mkdirs(SFTPRepository.java:186)
        at org.apache.ivy.plugins.repository.sftp.SFTPRepository.mkdirs(SFTPRepository.java:184)
        at org.apache.ivy.plugins.repository.sftp.SFTPRepository.put(SFTPRepository.java:160)
        ... 37 more

However if I simply run the same target again, the install completes successfully!

It seems to be some issue with creating a directory, from com.jcraft.jsch.ChannelSftp.mkdir(ChannelSftp.java:2142) in the stacktrace.

After running the 1st time, the testOrg/testModuleName directory exists (only testOrg having previously existed).

The 2nd time running the testOrg/testModuleName/1.2.3 directory is created (along with the library artifacts).

If after running the 1st time I delete the testOrg/testModuleName directory it created, it will continue to return the code 4 error.

My ANT library directory contains: jsch-0.1.50.jar which I assume it is using to upload to the destination Ivy Server.

In addition I am using:

  • Ant 1.8.4
  • Ivy 2.4.0
  • Java 1.7.0_80

Answer

By debugging the Ivy SFTP source code that creates the new directories on the destination toRepo repository, I was able to see why this was happening. The code is in the method: SFTPRepository.mkdirs() this recursively calls itself to make each directory in the path if they do not exist.

For my example the directory being uploaded was: /toRepo/testOrg/testModuleName//1.2.3/

You can see the double slash: // in the middle of the path. The meant that the mkdirs() method tried to create the testModuleName directory twice. The 2nd time failed which caused the code 4 error.

The reason there is a double slash in the path is because there is no branch for this artifact.

Within my ivy settings file the sftp resolver (for my toRepo repository) artifact patterns were configured to:

<ivy pattern="/toRepo/[organisation]/[module]/[branch]/[revision]/ivy-[revision].xml"/>
<artifact pattern="/toRepo/[organisation]/[module]/[branch]/[revision]/[artifact]-[revision].[ext]"/>

The /[branch]/ part of the pattern is what was generating the // in the path. There are 2 configurations, one for the ivy.xml file itself and the other for all other artifacts.

Ivy patterns allow the use of parenthesis for optional parts of the pattern. So changing my configuration to:

<ivy pattern="/toRepo/[organisation]/[module](/[branch])/[revision]/ivy-[revision].xml"/>
<artifact pattern="/toRepo/[organisation]/[module](/[branch])/[revision]/[artifact]-[revision].[ext]"/>

Fixed the issue and the ivy install functioned as expected. This means that for antifacts where there is no branch defined (like 3rd party artifacts), then the branch directory will not be included in the path.