Skip to content

SFTP: downloading an empty file on a reused connection results in CURLE_TOO_MANY_REDIRECTS #19165

@blach

Description

@blach

I did this

In my app, I'm using libcurl for getting directory listings and downloading files using SFTP.

When attempting to download an empty file after listing a directory (so the connection is reused), I get the error code CURLE_TOO_MANY_REDIRECTS.

I can reproduce the issue with command line curl using the "--next" parameter to issue two commands to the same server:

In the home directory on my server, I have created the folder "empty_file_test". This contains the 0 byte file "empty.txt".

mkdir empty_file_test
cd empty_file_test
touch empty.txt

On the client, I then issue this curl command (redacted):

curl -vvv sftp://server/~/empty_file_test/ --next sftp://server/~/empty_file_test/empty.txt --output empty.txt

Here's the redacted log file:

== Info: [READ] client_reset, clear readers
== Info: Host [redacted] was resolved.
== Info: IPv6: (none)
== Info: IPv4: [redacted]
== Info: [SETUP] added
== Info:   Trying [redacted]...
== Info: [SETUP] Curl_conn_connect(block=0) -> 0, done=0
== Info: [SETUP] Curl_conn_connect(block=0) -> 0, done=0
== Info: [SETUP] Curl_conn_connect(block=0) -> 0, done=0
== Info: [SETUP] Curl_conn_connect(block=0) -> 0, done=0
== Info: [SETUP] Curl_conn_connect(block=0) -> 0, done=0
== Info: [SETUP] Curl_conn_connect(block=0) -> 0, done=0
== Info: [SETUP] Curl_conn_connect(block=0) -> 0, done=0
== Info: [SETUP] Curl_conn_connect(block=0) -> 0, done=1
== Info: Established connection to [redacted] ([redacted] port 22) from [redacted] port 55451 
== Info: libssh2 cryptography backend: openssl compatible
== Info: User: '[redacted]'
== Info: Initialized password authentication
== Info: Authentication complete
<= Recv data, 66 bytes (0x42)
0000: -rw-r--r--    1 [redacted]   [redacted]          0 Oct 20 17:33 empty.tx
0040: t.
-rw-r--r--    1 [redacted]   [redacted]          0 Oct 20 17:33 empty.txt
== Info: [WRITE] [OUT] wrote 66 body bytes -> 66
== Info: [WRITE] [PAUSE] writing 66/66 bytes of type 1 -> 0
== Info: [WRITE] download_write body(type=1, blen=66) -> 0
== Info: [WRITE] client_write(type=1, len=66) -> 0
<= Recv data, 59 bytes (0x3b)
0000: drwx------   11 [redacted]   [redacted]       4096 Oct 20 16:59 ...
drwx------   11 [redacted]   [redacted]       4096 Oct 20 16:59 ..
== Info: [WRITE] [OUT] wrote 59 body bytes -> 59
== Info: [WRITE] [PAUSE] writing 59/59 bytes of type 1 -> 0
== Info: [WRITE] download_write body(type=1, blen=59) -> 0
== Info: [WRITE] client_write(type=1, len=59) -> 0
<= Recv data, 58 bytes (0x3a)
0000: drwxr-xr-x    2 [redacted]   [redacted]       4096 Oct 20 17:33 ..
drwxr-xr-x    2 [redacted]   [redacted]       4096 Oct 20 17:33 .
Info: [WRITE] [OUT] wrote 58 body bytes -> 58
Info: [WRITE] [PAUSE] writing 58/58 bytes of type 1 -> 0
Info: [WRITE] download_write body(type=1, blen=58) -> 0
Info: [WRITE] client_write(type=1, len=58) -> 0
Info: [WRITE] [OUT] done
Info: [READ] client_reset, clear readers
Info: Connection #0 to host [redacted]:22 left intact
Info: [READ] client_reset, clear readers
Info: Reusing existing SFTP: connection with host [redacted]
Info: abort upload
Recv data, 0 bytes (0x0)
Info: [WRITE] [PAUSE] writing 0/0 bytes of type 81 -> 0
Info: [WRITE] download_write body(type=81, blen=0) -> 0
Info: [WRITE] client_write(type=81, len=0) -> 0
Info: [WRITE] xfer_write_resp(len=0, eos=1) -> 0
Info: Connection died, retrying a fresh connect (retry count: 1)
Info: [WRITE] [OUT] done
Info: [READ] client_reset, will rewind reader
Info: shutting down connection #0
curl: (47) Number of redirects hit maximum amount

As you can see, this ends with "curl: (47) Number of redirects hit maximum amount".

This does not happen when just downloading an empty file without listing the directory first. I guess it only happens when a connection is reused.

I expected the following

There should be no error.

curl/libcurl version

curl 8.16.0 (aarch64-apple-darwin24.4.0) libcurl/8.16.0 OpenSSL/3.6.0 zlib/1.2.12 brotli/1.1.0 zstd/1.5.7 AppleIDN libssh2/1.11.1 nghttp2/1.67.1 ngtcp2/1.17.0 nghttp3/1.12.0 librtmp/2.3
Release-Date: 2025-09-10
Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns ldap ldaps mqtt pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp ws wss
Features: alt-svc AsynchDNS brotli GSS-API HSTS HTTP2 HTTP3 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM SPNEGO SSL threadsafe TLS-SRP UnixSockets zstd

operating system

Darwin Mac-Studio-von-Alexander.local 24.6.0 Darwin Kernel Version 24.6.0: Mon Aug 11 21:16:34 PDT 2025; root:xnu-11417.140.69.701.11~1/RELEASE_ARM64_T6020 arm64

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions