Image upload from API route on cloudinary works on localhost but not on vercel production

Options
vnvm
vnvm Member Posts: 8
edited November 2023 in Developer APIs

While the above route works perfectly fine while uploading files running on localhost, when i push to vercel it the AXIOS request will get a strange "405 Method Not Allowed" error while on vercel logs "Unknown application error occurred Runtime.Unknown"


export async function POST(req: Request) {
  try {
    const formData = await req.formData();
    const banner = formData.get("banner") as File;

    const arrayBuffer = await banner.arrayBuffer();
    const buffer = new Uint8Array(arrayBuffer);

    const results: any = await new Promise((resolve, reject) => {
      cloudinary.uploader
        .upload_stream(
          {
            folder: "demo",
          },
          function (error, result) {
            if (error) {
              reject(error);
              return;
            }
            resolve(result);
          }
        )
        .end(buffer);
    });

    const { secure_url } = results;
    return NextResponse.json({ data: secure_url });
  } catch (error) {
    console.error(error);
    return NextResponse.json(
      {
        message: "An error occurred while processing the request.",
      },
      { status: 500 }
    );
  }
}


Tagged:

Answers

  • DannyFromCloudinary
    DannyFromCloudinary Member, Cloudinary Staff Posts: 101
    Options

    Hey there! Thanks for getting in touch

    The Next package is actually a community developed library. This library is developed, tested, and maintained by the community, which means we don’t directly support it and so we can’t guarantee that PRs/issues on those repos will get the attention you may expect.

    I'm afraid, in this instance, we won't be able to provide specific troubleshooting or diagnostic information. Instead, I would suggest you reach out to the developer either via Github or Twitter. Links for both can be found here: https://www.npmjs.com/package/next-cloudinary#%EF%B8%8F-community--support

    Alternatively, as things work locally but not on Vercel, you may want to try the Vercel community over at https://vercel.com/help#issues

    I hope this helps. Please let me know if you have any further questions.

    Best regards,

    -Danny

  • vnvm
    vnvm Member Posts: 8
    Options

    I don't use next-cloudinary but

    import { v2 as cloudinary } from "cloudinary";

    cloudinary.uploader.upload_stream()

    as you can tell by the code i've provided


    thanks for your answer anyway

  • DannyFromCloudinary
    DannyFromCloudinary Member, Cloudinary Staff Posts: 101
    Options

    My apologies! I saw the usage of NextResponse.json and overlooked upload_stream(). Vercel's support staff will probably be best-placed to advise here, but if you let me know your cloud name, I can see if there is anything on our internal logging that may point to a root-cause for your problem.

    Thanks,

    -Danny

  • vnvm
    vnvm Member Posts: 8
    Options

    there you go

    NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME="dmz4yyl6i"

    however since it works on localhost i quess theres some kind of vercel incompatibility with the way i am handling the upload process with your SDK

  • DannyFromCloudinary
    DannyFromCloudinary Member, Cloudinary Staff Posts: 101
    Options

    Thanks.

    I've had a look and I see that we're seeing errors of "ArgumentError: invalid byte sequence in UTF-8" since October 31st 2023, 20:51:09 (UTC). What's interesting is our logging shows the file is being appended to the API key.

    It may be worth checking exactly how the application is sending the data when deployed to Vercel. Perhaps using something like POSTing to webhook.site or similar both on and off of Vercel and see how they compare.

    Kind regards,

    -Danny

  • vnvm
    vnvm Member Posts: 8
    Options

    Thanks for your asnwer.

    https://webhook.site/#!/2c531c9b-126a-427e-ab3c-7d938f81e035/

    I don't really see any differece that should cause this. I ll dig more into it

  • vnvm
    vnvm Member Posts: 8
    Options

    an update with the vercel's logs

    (node:8) ExperimentalWarning: buffer.File is an experimental feature and might change at any time

    (Use `node --trace-warnings ...` to show where the warning was created)

    Unhandled Promise Rejection {"errorType":"Runtime.UnhandledPromiseRejection","errorMessage":"[object Object]","reason":{"message":"Server return invalid JSON response. Status Code 500. SyntaxError: Unexpected token < in JSON at position 0","name":"Error","http_code":500},"promise":{"exception":{"message":"Server return invalid JSON response. Status Code 500. SyntaxError: Unexpected token < in JSON at position 0","name":"Error","http_code":500}},"stack":["Runtime.UnhandledPromiseRejection: [object Object]"," at process.<anonymous> (file:///var/runtime/index.mjs:1276:17)"," at process.emit (node:events:529:35)"," at /var/task/.next/server/chunks/9636.js:38:8381"," at runSingle (/var/task/.next/server/chunks/9636.js:38:451)"," at flush (/var/task/.next/server/chunks/9636.js:38:397)"," at process.processTicksAndRejections (node:internal/process/task_queues:77:11)"]}

    Unknown application error occurred

    Runtime.Unknown

  • vnvm
    vnvm Member Posts: 8
    Options

    {

    message: 'Server return invalid JSON response. Status Code 500. SyntaxError: Unexpected token < in JSON at position 0',

    name: 'Error',

    http_code: 500

    }

  • CloudinarySam
    CloudinarySam Administrator, Cloudinary Staff Posts: 22
    Options

    @vnvm - Some ideas for you!

    Check Encoding: The "invalid byte sequence in UTF-8" error suggests there may be an issue with character encoding. Ensure that the data you're sending to Cloudinary is encoded in UTF-8. Check your file encoding, especially if you're working with non-ASCII characters.

    Verify Environment Variables: Confirm that your environment variables are correctly set both locally and on Vercel. The NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME variable should be set correctly in your Vercel environment.

    Network Differences: Since the issue occurs on Vercel but not locally, consider differences in network environments. Ensure that Vercel allows the necessary outbound connections to Cloudinary. Check for any firewall or network restrictions that might affect the communication between your application and Cloudinary's API.

    Review Error Logs: The error message indicates "SyntaxError: Unexpected token < in JSON at position 0." This often suggests that the response from the server is not valid JSON. Review the response from the Cloudinary API and ensure it is properly formatted JSON.

    Node.js Version: The warning about the experimental feature "buffer.File" suggests that you are using an experimental feature in Node.js. Make sure that your Node.js version is compatible with the libraries and features you are using. Consider using a more stable version if necessary. https://nodejs.org/en/download

    Contact Vercel Support: If you're unable to resolve the issue, it might be beneficial to reach out to Vercel support for assistance, especially since the issue occurs on their platform. https://vercel.com/contact

  • vnvm
    vnvm Member Posts: 8
    Options

    Thanks for the hints.

    I've seen more people reporting this, so its not only me

    https://stackoverflow.com/questions/77258583/fileupload-not-working-on-build-error-500-nextjs-app-router-cloudinary

    https://stackoverflow.com/questions/77313990/how-to-upload-images-or-files-in-next-js-app-deployed-to-vercel

    Vercels support will not reply if not on a paid plan, and their community is not helpful at all.

    the promise is being rejected with the following error which is not explanoty at all,

    {

    message: 'Server return invalid JSON response. Status Code 500. SyntaxError: Unexpected token < in JSON at position 0',

    name: 'Error',

    http_code: 500

    }

    and results are undefiend

    i've checked the parsed data and they are identicall to the ones provided while on localhost, i really have no idea why this could be happening

    the request seems to leave vercel, but cloudinary returns wrong bad response for some reason

  • epasos
    epasos Member, Cloudinary Staff Posts: 23
    edited November 2023
    Options

    @vnvm Using the SDK method upload_stream, there is an unhandled error when the method is invoked in a build NextJS environment. An error HTML page is being received as a response instead of a JSON data format, hence, the error HTTP 500 is raised.

    As an alternative to the use of upload_stream, the `upload` method of the Node SDK together with a Data URI can be used, for example:

    import { v2 as cloudinary } from "cloudinary";
    import { NextResponse } from "next/server";
    
    // Cloudinary config
    cloudinary.config({
      cloud_name: "your_cloud_name",
      api_key: "your_api_key",
      api_secret: "your_api_secret",
      secure: true,
    });
    
    export const POST = async (req) => {
      
      const data = await req.formData();
      const image = await data.get("image");
      const fileBuffer = await image.arrayBuffer();
    
      var mime = image.type; 
      var encoding = 'base64'; 
      var base64Data = Buffer.from(fileBuffer).toString('base64');
      var fileUri = 'data:' + mime + ';' + encoding + ',' + base64Data;
    
      try {
        
        const uploadToCloudinary = () => {
          return new Promise((resolve, reject) => {
    
              var result = cloudinary.uploader.upload(fileUri, {
                invalidate: true
              })
                .then((result) => {
                  console.log(result);
                  resolve(result);
                })
                .catch((error) => {
                  console.log(error);
                  reject(error);
                });
          });
        };
    
        const result = await uploadToCloudinary();
        
        let imageUrl = result.secure_url;
    
        return NextResponse.json(
          { success: true, imageUrl: imageUrl },
          { status: 200 }
        );
      } catch (error) {
        console.log("server err", error);
        return NextResponse.json({ err: "Internal Server Error" }, { status: 500 });
      }
    };
    

    Hope this helps.

  • vnvm
    vnvm Member Posts: 8
    Options

    Thank you @epasos . It worked like a charm with the upload method and now my issue seems to be resolved for now. Is Cloudinary about to investigate further that "unhandled" error on future SDK releases?

  • epasos
    epasos Member, Cloudinary Staff Posts: 23
    Options

    @vnvm Thanks for the update and I am glad it can address your use case. As for the uploading of files in their byte array buffer format, I have raised an internal ticket for review and to provide the needed fix.