Search code examples
javascriptreactjscontentfulcontentful-managementcontentful-api

Contentful Content Management API Error 422 When Creating Asset


I am trying to create and publish an image as an asset using the Contentful Content Management API and have been unsuccessful so far, I have been able to successfully create and publish an entry and I cannot figure out why asset is not working. Here is my code for creating an asset. The eventual goal is to make this work for an array of images/attachments but I am trying to get it working with just one before I handle multiple.

  makeAsset = async (item) => {
    try {
      var MClient = createClient({
        accessToken: process.env.REACT_APP_CONTENTFUL_MANAGEMENT_ACCESS_TOKEN,
      });
      let space = await MClient.getSpace(
        process.env.REACT_APP_CONTENTFUL_API_SPACE
      );
      let environment = await space.getEnvironment(
        process.env.REACT_APP_CONTENTFUL_ENVIRONMENT
      );

      const asset = await environment.createAsset({
        fields: {
          title: {
            "en-US": item.imgNames[0],
          },
          file: {
            "en-US": {
              fileName: item.images[0].name,
              contentType: item.images[0].type,
              uploadFrom: item.imgUrls[0],
            },
          },
        },
      });

      const processedAsset = await asset.processForAllLocales();
      processedAsset.publish();

And the error in the console is this:

ValidationFailed: {
  "status": 422,
  "statusText": "",
  "message": "Validation error",
  "details": {
    "errors": [
      {
        "name": "type",
        "value": "data:image/png;base64,iVBORw0KGg(The rest of the image URL from above)
        "type": "Object",
            "details": "The type of \"value\" is incorrect, expected type: Object",
            "path": [
            "fields",
            "file",
            "en-US",
            "uploadFrom"
            ]
         }
       ]
     },
"request": {
    "url": "assets",
    "headers": {
      "Accept": "application/json, text/plain, */*",
      "Content-Type": "application/vnd.contentful.management.v1+json",
      "X-Contentful-User-Agent": "sdk contentful-management.js/5.26.1; platform browser; os Windows;",
      "Authorization": "Bearer ...7ijJE"
    },
    "method": "post",
    "payloadData": "{\"fields\":{\"title\":{\"en-US\":\"scuba_mask\"},\"file\":{\"en-US\":{\"fileName\":\"scuba_mask.png\",\"contentType\":\"image/png\",\"uploadFrom\":\"data:image/png;base64,iVBORw0KG(The rest of image URL)

I have been trying to search for other example because the documentation is patchy and none of the examples are working for me. One solution I tried was using the fs.createReadStream() function but that was removed from React.


Solution

  • @stefan judis, I used the code from the example and one of the functions is being deprecated in newer versions so I figured I would go out on a limb and replace something and it worked. For future reference for anyone else with this issue here is the solution that fixed my problem:

    makeAsset = async (item) => {
    try {
      //Contentful API Call
      var MClient = createClient({
        //Fetch access token from environment variables
        accessToken: process.env.REACT_APP_CONTENTFUL_MANAGEMENT_ACCESS_TOKEN,
      });
      //API call that requests the specified space
      let space = await MClient.getSpace(
        process.env.REACT_APP_CONTENTFUL_API_SPACE
      );
      let environment = await space.getEnvironment(
        process.env.REACT_APP_CONTENTFUL_ENVIRONMENT
      );
    
      const file = item.images[0];
      const contentType = file.type;
      const fileName = file.name;
      let asset = await environment.createAssetFromFiles({
        fields: {
          title: {
            "en-US": fileName,
          },
          file: {
            "en-US": {
              contentType,
              fileName,
              file,
            },
          },
        },
      });
      asset = await asset.processForAllLocales();
      asset.publish();
    } catch(error) {
      console.log(error);
    }
    }