Description
Issue
When using tus-js-client in Node.js environments, I've discovered that uploads can hang indefinitely with no retry mechanism being triggered, particularly in poor or unreliable network conditions (like satellite connections).
After investigating, I found that NodeHttpStack
does not specify any default timeout for HTTP requests. Since Node.js defaults to no timeout (0 = infinite), this means requests can remain in a "stalled" state forever without ever triggering an error that would initiate the retry mechanism.
Impact
This is a critical issue for resumable uploads, especially in environments with unreliable connections:
- Uploads silently hang with no errors or retries
- Even when network conditions improve, stalled uploads remain stalled due to TCP backoff
- Resources remain tied up indefinitely
- The retry mechanism (a key feature of the library) is never triggered for these cases
Reproduction
- Create a Node.js service using tus-js-client
- Initiate an upload over an unreliable connection
- During upload, introduce severe packet loss or connection degradation
- Observe that the upload stalls indefinitely with no retry
Workaround
I've had to copy paste the NodeHttpStack
module into our own codebase and modify it to include timeouts. I would have preferred to import the module directly, but it's not properly exported from your library in a way that makes it easily accessible.
The fix was simple:
const httpStack = new NodeHttpStack({
timeout: 30000, // 30 seconds
})
Proposed Solution
A simple fix would be to:
- Add a reasonable default timeout to the NodeHttpStack constructor
- Properly export the
NodeHttpStack
class so it can be imported directly (you let us inject a custom implementation)
This would ensure that hanging connections eventually trigger the retry mechanism, which is essential for a resumable upload library designed for unreliable networks.
Questions
- Was this omission intentional, or was it an oversight?
- Are there any technical reasons why a default timeout wasn't included?
- Would you consider adding a reasonable default timeout in a future release?