Search code examples
javascriptamazon-s3next.jsaws-sdkvercel

AWS S3 SDK - Upload from Next.js API endpoint on Vercel - ERR_HTTP_HEADERS_SENT


I am attempting to upload a file from my Next.js API endpoint that is running on Vercel using the @aws-sdk/client-s3 package. Here is an example:

import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
import type { NextApiRequest, NextApiResponse } from "next";

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  const s3Client = new S3Client({});

  const uploadCommand = new PutObjectCommand({
    Bucket: process.env.MY_S3_BUCKET,
    Key: "test/testUpload.json",
    Body: JSON.stringify({ message: "Hello World" }),
  });

  const response = await s3Client.send(uploadCommand);

  res.status(200).json(response);
}

This code will function completely fine on my localhost and upload the file as expected to s3. However once this is deployed to my Vercel environment I am receiving the following error from within the @aws-sdk package.

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at new NodeError (node:internal/errors:399:5)
    at ClientRequest.setHeader (node:_http_outgoing:663:11)
    at mod.request (/var/task/___vc/__launcher.js:90:17)
    at /var/task/node_modules/@aws-sdk/node-http-handler/dist-cjs/node-http-handler.js:70:25
    at new Promise (<anonymous>)
    at NodeHttpHandler.handle (/var/task/node_modules/@aws-sdk/node-http-handler/dist-cjs/node-http-handler.js:49:16)
    at async /var/task/node_modules/@aws-sdk/middleware-serde/dist-cjs/deserializerMiddleware.js:5:26 {
  code: 'ERR_HTTP_HEADERS_SENT',
  '$metadata': { attempts: 1, totalRetryDelay: 0 }
}

Using the following package version:

"@aws-sdk/client-s3": "3.278.0",

I have verified my environment variables for the S3 Client connection several times, and also tried several different ways to pass the body/key of the object. I have also tried using promise chaining instead of await, and removing the await all together. Finally tried as well returning the response from the endpoint instead of how I have it in the example.

The oddest thing about this is that it was working at one point, and I still have files from that successful upload in the bucket.

Any thoughts/insight would be much appreciated.


Solution

  • Swarnava from Vercel team here. We have pushed a fix for this.