Cole
Cole

Reputation: 464

Why does my server action not run when I pass in images that are too large using Next.js 14?

The following code is in a client component. I'm using a server action to add a product to my DB and images to my storage. When I try to add a product that has images that add up to at least 2MB the code stops at "Before Action". This also only happens in production and I'm using the hobby tier on Vercel for that. In production I get a client error that is: "TypeError: Cannot destructure property 'errorMessage' of '(intermediate value)' as it is undefined.". Within the addProdcutAction I have a try catch block so that server action should only ever return {errorMessage: string | null}. I also have console.warn("A") as the first line of the server action and it doesn't show up in the Vercel logs. I'm thinking that the error occurs in the passing of the data from the client to the server action. Maybe there's a limit with Vercel that I'm unaware of. Has anyone ever encountered an error like this before? Thanks.

const handleAddProduct = async (formData: FormData) => {
  if (imageUrls.length === 0) {
    toast.error("Must add at least one image");
    return;
  }
  if (!formData.get("category")) {
    toast.error("Must select a category");
    return;
  }

  console.warn("Start");

  startTransition(async () => {
    console.warn("Start Transition");

    const boundFormData = new FormData();
    // add images files to form data
    for (const imageUrl of imageUrls) {
      const imageFile = await convertBlobUrlToFile(imageUrl);
      boundFormData.append("imageFiles", imageFile);
    }

    const boundAddProductAction = addProductAction.bind(null, boundFormData);
    // run action
    console.warn("Before Action");

    const { errorMessage } = await boundAddProductAction(formData);

    console.warn("After Action");

    if (!errorMessage) {
      setModalState((prev) => ({ ...prev, isOpen: false }));
      toast.success("Product successfully added");
    } else {
      toast.error(errorMessage);
    }
  });
};

Upvotes: 0

Views: 1161

Answers (1)

Arash Jahan Bakhshan
Arash Jahan Bakhshan

Reputation: 1160

There are 2 limitations.

One is from Vercel which is maximum 4.5MB in NodeJS runtime and 4MB in edge runtime. more information can be found in the official documentation (https://vercel.com/docs/functions/runtimes#size-limits)

Another one is from NextJS which is 1MB as they've said here:

By default, the maximum size of the request body sent to a Server Action is 1MB, to prevent the consumption of excessive server resources in parsing large amounts of data, as well as potential DDoS attacks.

you can change the limit to as much as you want in your next.config.js file:

/** @type {import('next').NextConfig} */
 
module.exports = {
  experimental: {
    serverActions: {
      bodySizeLimit: '2mb', // maximum `4.5MB/4MB` if you are using Vercel
    },
  },
}

However, I recommend you use a cloud storage such as S3 or Google Cloud Storage. they provide a lot of useful APIs that are easy to use and performant without any limitations. They keep your files safe and secure. server actions are not meant to be used for file uploading.

Upvotes: 1

Related Questions