Skip to content

[lib-storage] Upload.done() never resolves after large streaming upload (unknown size) #7729

@fooman5000

Description

@fooman5000

Checkboxes for prior research

Describe the bug

When using Upload from @aws-sdk/lib-storage with a streaming body of unknown size (no ContentLength), after all data has been written and the stream is ended, upload.done() can never resolve. The multipart upload completes successfully on S3 (all parts uploaded, object is usable), but the promise from done() never settles, so the application hangs until manually stopped.
This is different from #5652 (Upload stuck with empty file readable stream). Our case is large streaming payloads (e.g. 35–45 GB) from a PassThrough (or similar) stream where total size is unknown up front.

Regression Issue

  • Select this option if this issue appears to be a regression.

SDK version number

@aws-sdk/client-s3@3.621.0, @aws-sdk/lib-storage@3.490.0 (also observed in same scenario with other 3.x versions).

Which JavaScript Runtime is this issue in?

Node.js

Details of the browser/Node.js/ReactNative version

Node.js 20.x (LTS)

Reproduction Steps

Create a PassThrough (or other readable) stream as the upload body.
Create Upload with { client, params: { Bucket, Key, Body: stream } } — do not set ContentLength (streaming/unknown size).
Start the upload with upload.done() and write a large amount of data to the stream (e.g. tens of GB) over time.
When the export is finished, call stream.end() so the stream closes.
Await upload.done() (e.g. in a “close” or “shutdown” path).

Observed Behavior

The process hangs at the await upload.done() step. No resolve or reject. The object in S3 is complete and correct; only the promise never settles.

Expected Behavior

done() should resolve with CompleteMultipartUploadCommandOutput (or reject with an error) once the stream has ended and the final CompleteMultipartUpload has been sent and responded to.

Possible Solution

Wrapping upload.done() in a timeout (e.g. Promise.race with a timer) so the application does not block indefinitely. This avoids the hang but does not fix the underlying behavior.

Additional Information/Context

We use the recommended pattern: Upload from lib-storage with a stream body for large/streaming uploads.
We do not pass checksums (e.g. ChecksumSHA256).
Occurrence is intermittent; not every large streaming run hangs, but when it does, it is consistently at the same point (after stream end, waiting on done()).

Metadata

Metadata

Assignees

Labels

bugThis issue is a bug.p2This is a standard priority issue

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions