Skip to content

Error thrown outside of the promise chain (Error: write EPIPE)Β #7251

@vokrik

Description

@vokrik

Checkboxes for prior research

Describe the bug

We have this code in our application:

try {
 await this.s3Client.send(
      new PutObjectCommand({
        Bucket: this.config.bucketName,
        Key: id,
        Body: data,
      }),
    );
} catch(error) {
  // handle error
}

The app started in certain situations crashing. We investigated that the crash occurs when we try to upload 50+MB files. We have an S3 proxy on a way towards the AWS s3, that has a very low setting for mas file size and when we reach it, it seems to just close the connection. (and an error write EPIPE is thrown.)

Now of course the problem is with the misconfigured S3 proxy, however the handling of the S3Client seems to be wrong as well.

It seems that the error is thrown outside of the promise chain:

Simplest example of such a case:

try {
await new Promise((resolve, reject) => {
  setTimeout(() => throw new Error('This will not be caught'), 100);
  resolve(true);
});
} catch (error) {
  
}

I believe that in the SDK there might be some upload stream that isn't properly handled if it fails.

Regression Issue

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

SDK version number

@aws-sdk/[email protected]

Which JavaScript Runtime is this issue in?

Node.js

Details of the browser/Node.js/ReactNative version

20.19.2

Reproduction Steps

Spin up a https://github.com/gaul/s3proxy in a test container,
Upload a file using PutObjectCommand that is bigger than cca 50MB

For example I have created this test:

  it("should upload buffer", async () => {
    const fn = async () => {
      await s3Client.send(
        new PutObjectCommand({
          Bucket: randomBucketName,
          Key: crypto.randomUUID(),
          Body: Buffer.alloc(100_000_000, 0),
        }),
      );
    };

    fn().catch((err) => {
      console.error("Catching error: ", err);
    });

    // This is just a sleep so that the test doesn't finish immediately
    await new Promise((resolve) => {
      setTimeout(resolve, 10000);
    });
  });

Against this container:

 new GenericContainer("andrewgaul/s3proxy:s3proxy-2.6.0")
      .withEnvironment({
        JCLOUDS_PROVIDER: "transient-nio2", // in memory storage
        JCLOUDS_REGIONS: "us-west-1",
      })
      .withExposedPorts(80)
      .start(),

Observed Behavior

The error "Request Too Big is caught", however another error EPIPE is thrown and gets caught by vitest. You can see that it's not thrown within the context of the test, but rather outside of the promise chain, making the report looking strange (tests succeeds, but the test suit fails)

Image Image

Expected Behavior

The EPIPE is handled within the aws-sdk and it doesn't get thrown. Would do it on the user side but I have no access to the underlying stream

Possible Solution

No response

Additional Information/Context

No response

Metadata

Metadata

Assignees

Labels

bugThis issue is a bug.closed-for-stalenessp2This is a standard priority issueresponse-requestedWaiting on additional info and feedback. Will move to \"closing-soon\" in 7 days.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions