Skip to content

sftp.put hangs after creating the file #247

Closed

Description

@p-j

Hi,

I'm trying to do a simple upload of a small CSV file I'm generating on the fly.
Here is the relevant portion of the code

const data = Buffer.from(csv)
const sftp = new Client()
try {
  await sftp.connect({
    host: HOST,
    username: USERNAME,
    password: PASSWORD,
    port: PORT,
    debug: console.info
  })
  await sftp.put(data, '/path/to/file.csv')
} catch (e) {
  console.error(e)
} finally {
  await sftp.end()
}

When doing so, most of the time the upload will hang, with logs showing:

CLIENT[sftp]: exists -> /path/to/file.csv
CLIENT[sftp]: stat -> /path/to/file.csv
DEBUG[SFTP]: Outgoing: Writing STAT
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Parser: IN_PACKET
DEBUG: Parser: Decrypting
DEBUG: Parser: pktLen:60,padLen:9,remainLen:48
DEBUG: Parser: IN_PACKETDATA
DEBUG: Parser: Decrypting
DEBUG: Parser: HMAC size:32
DEBUG: Parser: IN_PACKETDATAVERIFY
DEBUG: Parser: Verifying MAC
DEBUG: Parser: IN_PACKETDATAVERIFY (Valid HMAC)
DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_DATA (0)
DEBUG[SFTP]: Parser: Response: ATTRS
CLIENT[sftp]: stats <-  {
 "mode": 33206,
 "permissions": 33206,
 "uid": 1026,
 "gid": 100,
 "size": 0,
 "atime": 1595344292,
 "mtime": 1595347428
}
CLIENT[sftp]: Removing listener from error
CLIENT[sftp]: Removing listener from close
DEBUG: Parser: IN_PACKETBEFORE (expecting 16)
CLIENT[sftp]: exists <-  {
 "mode": 33206,
 "uid": 1026,
 "gid": 100,
 "size": 0,
 "accessTime": 1595344292000,
 "modifyTime": 1595347428000,
 "isDirectory": false,
 "isFile": true,
 "isBlockDevice": false,
 "isCharacterDevice": false,
 "isSymbolicLink": false,
 "isFIFO": false,
 "isSocket": false
}
CLIENT[sftp]: put remote path info  {
 "path": "/path/to/file.csv",
 "type": "-",
 "valid": true
}
CLIENT[sftp]: put -> /path/to/file.csv
DEBUG[SFTP]: Outgoing: Writing OPEN
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
CLIENT[sftp]: put source is a buffer
DEBUG: Parser: IN_PACKET
DEBUG: Parser: Decrypting
DEBUG: Parser: pktLen:44,padLen:17,remainLen:32
DEBUG: Parser: IN_PACKETDATA
DEBUG: Parser: Decrypting
DEBUG: Parser: HMAC size:32
DEBUG: Parser: IN_PACKETDATAVERIFY
DEBUG: Parser: Verifying MAC
DEBUG: Parser: IN_PACKETDATAVERIFY (Valid HMAC)
DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_DATA (0)
DEBUG[SFTP]: Parser: Response: HANDLE
DEBUG[SFTP]: Outgoing: Writing FSETSTAT
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Parser: IN_PACKETBEFORE (expecting 16)
DEBUG: Parser: IN_PACKET
DEBUG: Parser: Decrypting
DEBUG: Parser: pktLen:44,padLen:6,remainLen:32
DEBUG: Parser: IN_PACKETDATA
DEBUG: Parser: Decrypting
DEBUG: Parser: HMAC size:32
DEBUG: Parser: IN_PACKETDATAVERIFY
DEBUG: Parser: Verifying MAC
DEBUG: Parser: IN_PACKETDATAVERIFY (Valid HMAC)
DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_DATA (0)
DEBUG[SFTP]: Parser: Response: STATUS
DEBUG[SFTP]: Outgoing: Writing WRITE
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Parser: IN_PACKETBEFORE (expecting 16)
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Parser: IN_PACKET
DEBUG: Parser: Decrypting
DEBUG: Parser: pktLen:28,padLen:18,remainLen:16
DEBUG: Parser: IN_PACKETDATA
DEBUG: Parser: Decrypting
DEBUG: Parser: HMAC size:32
DEBUG: Parser: IN_PACKETDATAVERIFY
DEBUG: Parser: Verifying MAC
DEBUG: Parser: IN_PACKETDATAVERIFY (Valid HMAC)
DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_WINDOW_ADJUST (0, 98482)
DEBUG: Parser: IN_PACKETBEFORE (expecting 16)

and it will stay like so forever

Sometime, completely at random, it will go through and in thise case the logs will be like that:

CLIENT[sftp]: exists -> /path/to/file.csv
CLIENT[sftp]: stat -> /path/to/file.csv
DEBUG[SFTP]: Outgoing: Writing STAT
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Parser: IN_PACKET
DEBUG: Parser: Decrypting
DEBUG: Parser: pktLen:60,padLen:9,remainLen:48
DEBUG: Parser: IN_PACKETDATA
DEBUG: Parser: Decrypting
DEBUG: Parser: HMAC size:32
DEBUG: Parser: IN_PACKETDATAVERIFY
DEBUG: Parser: Verifying MAC
DEBUG: Parser: IN_PACKETDATAVERIFY (Valid HMAC)
DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_DATA (0)
DEBUG[SFTP]: Parser: Response: ATTRS
CLIENT[sftp]: stats <-  {
 "mode": 33206,
 "permissions": 33206,
 "uid": 1026,
 "gid": 100,
 "size": 0,
 "atime": 1595344292,
 "mtime": 1595347522
}
CLIENT[sftp]: Removing listener from error
CLIENT[sftp]: Removing listener from close
DEBUG: Parser: IN_PACKETBEFORE (expecting 16)
CLIENT[sftp]: exists <-  {
 "mode": 33206,
 "uid": 1026,
 "gid": 100,
 "size": 0,
 "accessTime": 1595344292000,
 "modifyTime": 1595347522000,
 "isDirectory": false,
 "isFile": true,
 "isBlockDevice": false,
 "isCharacterDevice": false,
 "isSymbolicLink": false,
 "isFIFO": false,
 "isSocket": false
}
CLIENT[sftp]: put remote path info  {
 "path": "/path/to/file.csv",
 "type": "-",
 "valid": true
}
CLIENT[sftp]: put -> /path/to/file.csv
DEBUG[SFTP]: Outgoing: Writing OPEN
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
CLIENT[sftp]: put source is a buffer
DEBUG: Parser: IN_PACKET
DEBUG: Parser: Decrypting
DEBUG: Parser: pktLen:44,padLen:17,remainLen:32
DEBUG: Parser: IN_PACKETDATA
DEBUG: Parser: Decrypting
DEBUG: Parser: HMAC size:32
DEBUG: Parser: IN_PACKETDATAVERIFY
DEBUG: Parser: Verifying MAC
DEBUG: Parser: IN_PACKETDATAVERIFY (Valid HMAC)
DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_DATA (0)
DEBUG[SFTP]: Parser: Response: HANDLE
DEBUG[SFTP]: Outgoing: Writing FSETSTAT
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Parser: IN_PACKETBEFORE (expecting 16)
DEBUG: Parser: IN_PACKET
DEBUG: Parser: Decrypting
DEBUG: Parser: pktLen:44,padLen:6,remainLen:32
DEBUG: Parser: IN_PACKETDATA
DEBUG: Parser: Decrypting
DEBUG: Parser: HMAC size:32
DEBUG: Parser: IN_PACKETDATAVERIFY
DEBUG: Parser: Verifying MAC
DEBUG: Parser: IN_PACKETDATAVERIFY (Valid HMAC)
DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_DATA (0)
DEBUG[SFTP]: Parser: Response: STATUS
DEBUG[SFTP]: Outgoing: Writing WRITE
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Parser: IN_PACKETBEFORE (expecting 16)
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
DEBUG: Parser: IN_PACKET
DEBUG: Parser: Decrypting
DEBUG: Parser: pktLen:28,padLen:18,remainLen:16
DEBUG: Parser: IN_PACKETDATA
DEBUG: Parser: Decrypting
DEBUG: Parser: HMAC size:32
DEBUG: Parser: IN_PACKETDATAVERIFY
DEBUG: Parser: Verifying MAC
DEBUG: Parser: IN_PACKETDATAVERIFY (Valid HMAC)
DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_WINDOW_ADJUST (0, 98482)
DEBUG: Parser: IN_PACKETBEFORE (expecting 16)
DEBUG: Parser: IN_PACKET
DEBUG: Parser: Decrypting
DEBUG: Parser: pktLen:28,padLen:18,remainLen:16
DEBUG: Parser: IN_PACKETDATA
DEBUG: Parser: Decrypting
DEBUG: Parser: HMAC size:32
DEBUG: Parser: IN_PACKETDATAVERIFY
DEBUG: Parser: Verifying MAC
DEBUG: Parser: IN_PACKETDATAVERIFY (Valid HMAC)
DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_WINDOW_ADJUST (0, 102171)
DEBUG: Parser: IN_PACKETBEFORE (expecting 16)
DEBUG: Parser: IN_PACKET
DEBUG: Parser: Decrypting
DEBUG: Parser: pktLen:44,padLen:6,remainLen:32
DEBUG: Parser: IN_PACKETDATA
DEBUG: Parser: Decrypting
DEBUG: Parser: HMAC size:32
DEBUG: Parser: IN_PACKETDATAVERIFY
DEBUG: Parser: Verifying MAC
DEBUG: Parser: IN_PACKETDATAVERIFY (Valid HMAC)
DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_DATA (0)
DEBUG[SFTP]: Parser: Response: STATUS
DEBUG: Parser: IN_PACKETBEFORE (expecting 16)
DEBUG[SFTP]: Outgoing: Writing CLOSE
DEBUG: Outgoing: Writing CHANNEL_DATA (0)
CLIENT[sftp]: Removing listener from error
CLIENT[sftp]: Removing listener from close
DEBUG: Outgoing: Writing DISCONNECT (BY_APPLICATION)
CLIENT[sftp]: Removing listener from error

I'm currently running Node v14.4.0, so I'm wondering if this could be linked to mscdex/ssh2-streams#156 ?

You mention in this issue that using a concurrency of 1 it's working all the time, and my understanding was that client.put is running in the same configuration which is why I'm opening this issue here as I'm not sure it's the same.

Do you have any idea what I could do to ensure a more consistent result while running Node >= v14.1.0 ?

Thanks

Activity

  1. theophilusx commented on Jul 21, 2020

    @theophilusx
    Owner
  2. p-j commented on Jul 21, 2020

    @p-j
    Author

    Thanks for your response @theophilusx
    I plan on checking this by the end of the week. I'll be posting some feedback then.

  3. p-j commented on Jul 23, 2020

    @p-j
    Author

    Hi @theophilusx
    I've tested both Node v13.14 and Node v14.5 today.
    Both works fine with very small files.
    Moving to larger files (in my case 842Ko CSV File)
    Node v13.14 continues to produce good result but Node v14.5 hangs after creating the file. I end up with an empty file on the sftp server.

    I'll be conducting more tests tomorrow with Node 14.0 & upward to see if the issue is indeed introduced by v14.1 as reported in the other issue.

  4. theophilusx commented on Jul 23, 2020

    @theophilusx
    Owner
  5. p-j commented on Jul 27, 2020

    @p-j
    Author

    I can confirm this is working on v14.0.0 and not on v14.1.0 with a big enough file.

  6. p-j commented on Jul 27, 2020

    @p-j
    Author

    I've also been able to reproduce the behavior with both

    On Node >= 14.1 node buffer-test.js 1000 /home/test will hang most of the time
    On Node <= 14.0 node buffer-test.js 1000 /home/test will go through most of the time

  7. theophilusx commented on Jul 27, 2020

    @theophilusx
    Owner
  8. theophilusx commented on Aug 4, 2020

    @theophilusx
    Owner
  9. theophilusx commented on Aug 4, 2020

    @theophilusx
    Owner
  10. p-j commented on Aug 4, 2020

    @p-j
    Author

    Hi @theophilusx
    I've made a small change to your script here: master...p-j:master
    This highlights the following, in v13.12.0 I get the following:

    jeremie@xps ➜  tools git:(master) ✗ node lowlevel-buffer-put.js 1000 /home/test/$(date +"%Y-%m-%d_%H-%M-%S").bin
    Uploading buffer of 1024000 bytes to /home/test/2020-08-04_09-46-02.bin
    write stream pipe
    read stream resume
    read stream data
    read stream pause
    read stream end
    File successfully uploaded to /home/test/2020-08-04_09-46-02.bin
    write stream unpipe
    

    while running v14.7.0

    jeremie@xps ➜  tools git:(master) ✗ nvm use v14.7   
    Now using node v14.7.0 (npm v6.14.7)
    jeremie@xps ➜  tools git:(master) ✗ node lowlevel-buffer-put.js 1000 /home/test/$(date +"%Y-%m-%d_%H-%M-%S").bin
    Uploading buffer of 1024000 bytes to /home/test/2020-08-04_09-46-38.bin
    write stream pipe
    read stream resume
    read stream data
    read stream pause
    read stream end
    read stream close
    ^C
    

    The difference being the close event being emitted in the v14.7 and not in the v13.12

  11. theophilusx commented on Aug 4, 2020

    @theophilusx
    Owner
  12. theophilusx commented on Aug 5, 2020

    @theophilusx
    Owner
  13. p-j commented on Aug 10, 2020

    @p-j
    Author

    Seems the root cause could be here nodejs/node#32887 (comment)

  14. theophilusx commented on Oct 24, 2020

    @theophilusx
    Owner

    The ssh2 module is being re-written to address this and some other limitations of that module. The ssh2-streams module is also being deprecated. This means a re-write of ssh2-sftp-client will be necessary to work with the updated ssh2 module.

    I have created the branch version-6, which will be used to do the re-write.

  15. p-j commented on Oct 26, 2020

    @p-j
    Author

    Thanks for the heads up, I might have some free time in the coming weeks if you want a hand in doing so I'd be happy to help.

  16. theophilusx commented on Jan 2, 2021

    @theophilusx
    Owner

    Update: I have recently tested against the new ssh2 version. While the issues specific to fastPut and fastGet appear to be resolved in the new ssh2 version, there are still some issues with put/get which appear to be related to streams. The seems to still be a bit of work required on the new version of ssh2 before it will be ready for a release.

    I have tested the existing 0.8.9 version of ssh2 against latest node v15.4.0. The changes introduced in node v14.x which caused problems with ssh2 have been rolled back. This means that ssh2 and ssh2-sftp-client seems to work OK with node version 15.4.0. However, the changes which were rolled back did provide significant performance improvements in other areas, so it is likely that at some point they will be re-applied in one fashion or another. Hopefully, the new version of ssh2 will be released before this occurs.

  17. theophilusx commented on Jun 4, 2021

    @theophilusx
    Owner

    A new version of ssh2 has been released which addresses the underlying issue which caused this issue. I will be releasing ssh2-sftp-client 7.0.0 in a week. The new version works with all known versions of node >= v10.

    I'm closing this issue as it has been resolved upstream with the new ssh2 version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions