Error When Trying to Upload an Image to Imgbb

I'm trying to upload images to ImgBB using NodeJS and GraphQL. I have a uploadImage mutation that takes an image in the form of a data url string, and goes as follows:

import parseDataUrl from "data-uri-to-buffer";

// ...

{
  Mutation: {
    async uploadImage(_, { dataUrl }) {
      const buffer = parseDataUrl(dataUrl); // 
      
      if (buffer.byteLength > 10 * 10 ** 6)
        throw new Error("The image exceeds the maximum size of 10 MB");

      const body = new FormData();
      body.append("image", buffer);

      const result = await fetch(
        `
        {
          method: "post",
          headers: { ...body.getHeaders() },
          body
        }
      ).then<any>(result => result.json());

      if (!result.success || !result.url) {
        const msg = result.error?.message;
        throw new Error(
          `There was an error during upload${msg ? `: ${msg}` : ""}`
        );
      }
      return result.url;
    }
  }
}

body.getHeaders() contains:

{
    'content-type': 'multipart/form-data; boundary=--------------
------------656587403243047934588601'
  }

(I'm using node-fetch)

But no matter the combinations of query params, headers and body I use, I always end up getting this error:

  {
    status_code: 400,
    error: { message: 'Undefined array key "scheme"', code: 0 },
    status_txt: 'Bad Request'
  }

I can't find anything about it, do you have an idea?

1

2 Answers

There are multiple things you can do to resolve your issue.

  1. Important thing with FormData, you need to explicitly provide a name for the image buffer if it's not already included, uploading without name API would throw the same error you have mentioned.
body.append("image", buffer, "addSomeImageName.png");
  1. The api does not require any header explicitly so you can remove it.
{
    method: "post",
    headers: { ...body.getHeaders() }, // This can be removed.
    body
}
  1. The logic you are using to check for the result is faulty and would always throw error even if the result is successful.
if (!result.success || !result.url) {  // Check for success flag only.
  const msg = result.error?.message;
  throw new Error(
    `There was an error during upload${msg ? `: ${msg}` : ""}`
  );
}

This is the block I tested and is working fine:

import parseDataUrl from "data-uri-to-buffer";
import fetch from 'node-fetch';
import FormData from "form-data";


async function uploadImage({
  dataUrl
}) {

  const buffer = parseDataUrl(dataUrl);

  if (buffer.byteLength > 10 * 10 ** 6)
    throw new Error("The image exceeds the maximum size of 10 MB");

  const body = new FormData();
  body.append("image", buffer, "someImageName.png");

  const result = await fetch(
    ` {
      method: "post",
      // headers: { ...body.getHeaders() },
      body
    }
  ).then(result => result.json())
  // .then(data => {
  //   console.log(data); // Working fine here too.
  // });

  console.log("-------result--------\n", result); // Result is fine.

  // Logic testing.
  console.log(result.success);
  console.log(result.url);
  console.log(!result.success);
  console.log(!result.url);
  console.log(!result.success || !result.url);


  if (!result.success || !result.url) {
    const msg = result.error ? .message;
    console.log(`There was an error during upload${msg ? `: ${msg}` : ""}`)
    // throw new Error(
    //   `There was an error during upload${msg ? `: ${msg}` : ""}`
    // );
  }

  return result.url;
}

console.log("--------------------- console result ------------------------")
console.log(uploadImage({
  dataUrl: "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"
}));

One thing that seems odd to me:

const buffer = parseDataUrl(dataUrl); // 

The package in the comment only offers the function dataUriToBuffer, which you are not using. Are you using parseDataUrl from jsdom? Are you using node-fetch's own implementation of FormData as supposed to according to the documentation?

Please append your question with all relevant import statements and please also share the contents of body.getHeaders().

1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

James H. Sterling

James H. Sterling

Environmental Science & Climate Journalist

James Sterling reports on renewable energy developments, climate policy, ecological conservation, and green tech innovations around the globe.

Share this article
Twitter Facebook Pinterest