fix: handle stream end properly in readChunk to avoid hanging on deferred-length uploads(Fixes #779) #780
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
What this PR does
Fixes a bug where uploads using Readable streams with uploadLengthDeferred: true would hang if the total stream size is an exact multiple of chunkSize.
Related Issue
Fixes #779
Root cause
When using tus-js-client with:
uploadLengthDeferred: true
a stream source (Readable stream in Node.js)
and a file whose size is an exact multiple of the chunk size (e.g. 14 bytes file with 7-byte chunks),
the upload hangs after the last chunk and never completes.
When the file size is an exact multiple of the chunk size, readChunk() finishes reading the last full chunk and assumes more data might still come. But since there's no more data, only 'end' fires — not 'readable' — and the Promise never resolves.
In contrast:
When fileSize % chunkSize ≠ 0, the last read() returns a smaller chunk.
After this, the internal loop breaks as expected.
Changes
Adds an 'end' event listener in readChunk() to resolve the read with an empty buffer when stream ends without triggering 'readable'.
Ensures upload completes correctly for edge cases involving deferred length and chunk alignment.
Adds a test to cover this scenario.
✅ Testing
New test: ✅ should accept Readable streams with deferred size when chunk size divides the upload size
Existing tests: ✅ All pass
BrowserStack tests failed due to missing credentials in CI. All other tests are passing and this failure is unrelated to the code changes.