Getting "Request failed with status code 422" randomly on PUT request to assets

Solved
diego_ezfy
Shopify Partner
2880 549 846

Overview

I'm creating an app that needs to store images. Since it's a small amount of images I'm using the own customer's theme for that. This is how I'm currently doing it in Node.JS:

 

      const headers = {
        "X-Shopify-Access-Token": ctx.cookies.get("accessToken"),
      };

      const themesURL = `https://${ctx.cookies.get(
        "shopOrigin",
      )}/admin/api/2020-04/themes.json`;

      const { data: themes } = await axios.get(themesURL, {
        headers,
      });

      const themeId = themes.themes.filter(({ role }) => role === "main")[0].id;

      const assetURL = `https://${ctx.cookies.get(
        "shopOrigin",
      )}/admin/api/2020-04/themes/${themeId}/assets.json`;

      const imageBase64 = item.imageSrc.replace(/^data:image\/\w+;base64,/, "");

      const { data } = await axios.put(
        assetURL,
        {
          asset: {
            key: `assets/highlight-bar-${uuid}.png`,
            attachment: imageBase64,
          },
        },
        {
          headers,
        },
      );

 


Issue

It works just fine, but occasionally it returns a 422 error. I thought it was because I was doing an excessive amount of requests within a short period of time, but I was able to store about 10 images within 30 seconds with no problems. After that I waited for a minute or so and got a 422. I really have no clue what's going on in here since I can't debug it any further.

Expected Behavior

I would like to know why this happens - why does it stop working seemingly out of nowhere? 

I tried handling this sort of error using async await retry with no success. 

Kindly shed some light on this if you can, I've been stuck on this for a while now. 

Thank you!

Accepted Solution (1)
diego_ezfy
Shopify Partner
2880 549 846

This is an accepted solution.

I found the solution.

Taking a look at the Shopify's API response codes I realized there was something wrong with the body of my request. Axios was not returning the proper error message, so I decided to use the Fetch API. 

After doing so I realized it was because my UUID variable was occasionally creating IDs using prohibited characters (e.g. "+", ">", etc) making Shopify reject the request. I fixed it by generating a numeric ID.

This is the final solution in case anyone needs it. I wrapped it in a function to make it easier to be re-utilized.

What it does is simply saving an image into the current user's theme:

const saveImageToTheme = async (ctx) => {
  return new Promise(async (resolve, reject) => {
    try {
      const uuid = new Date().valueOf();
      const accessToken = ctx.cookies.get("accessToken");

      let item = ctx.request.body;

      /* Store image in user's theme */
      const headers = {
        "X-Shopify-Access-Token": accessToken,
      };

      const themesURL = `https://${ctx.cookies.get(
        "shopOrigin",
      )}/admin/api/2020-04/themes.json`;

      const { data: themes } = await axios.get(themesURL, {
        headers,
      });

      const themeId = themes.themes.filter(({ role }) => role === "main")[0].id;

      const assetURL = `https://${ctx.cookies.get(
        "shopOrigin",
      )}/admin/api/2020-04/themes/${themeId}/assets.json`;

      const imageBase64 = item.imageSrc.replace(/^data:image\/\w+;base64,/, "");
      
      const body = JSON.stringify({
        asset: {
          key: `assets/highlight-bar-${uuid}.jpg`,
          attachment: imageBase64,
        },
      });

      let response = await fetch(assetURL, {
        method: "PUT",
        body,
        headers: {
          ...headers,
          Accept: "application/json",
          "Content-Type": "application/json",
        },
      });

      let data = await response.json();

      resolve(data);
    } catch (error) {
      reject(error);
    }
  });
};

 


View solution in original post

Reply 1 (1)
diego_ezfy
Shopify Partner
2880 549 846

This is an accepted solution.

I found the solution.

Taking a look at the Shopify's API response codes I realized there was something wrong with the body of my request. Axios was not returning the proper error message, so I decided to use the Fetch API. 

After doing so I realized it was because my UUID variable was occasionally creating IDs using prohibited characters (e.g. "+", ">", etc) making Shopify reject the request. I fixed it by generating a numeric ID.

This is the final solution in case anyone needs it. I wrapped it in a function to make it easier to be re-utilized.

What it does is simply saving an image into the current user's theme:

const saveImageToTheme = async (ctx) => {
  return new Promise(async (resolve, reject) => {
    try {
      const uuid = new Date().valueOf();
      const accessToken = ctx.cookies.get("accessToken");

      let item = ctx.request.body;

      /* Store image in user's theme */
      const headers = {
        "X-Shopify-Access-Token": accessToken,
      };

      const themesURL = `https://${ctx.cookies.get(
        "shopOrigin",
      )}/admin/api/2020-04/themes.json`;

      const { data: themes } = await axios.get(themesURL, {
        headers,
      });

      const themeId = themes.themes.filter(({ role }) => role === "main")[0].id;

      const assetURL = `https://${ctx.cookies.get(
        "shopOrigin",
      )}/admin/api/2020-04/themes/${themeId}/assets.json`;

      const imageBase64 = item.imageSrc.replace(/^data:image\/\w+;base64,/, "");
      
      const body = JSON.stringify({
        asset: {
          key: `assets/highlight-bar-${uuid}.jpg`,
          attachment: imageBase64,
        },
      });

      let response = await fetch(assetURL, {
        method: "PUT",
        body,
        headers: {
          ...headers,
          Accept: "application/json",
          "Content-Type": "application/json",
        },
      });

      let data = await response.json();

      resolve(data);
    } catch (error) {
      reject(error);
    }
  });
};