productVariantsBulkCreate deletes default title variant even when using default behaviour

Hi guys, I’ve had an issue where creating new variants for a product using the productVariantsBulkCreate deletes the standalone variant from the products and replaces it with the new variant.

The input requests a mandatory option for the new variant being created and even when using Title which is the default option the standalone variant gets deleted.

This has been very problematic for us since we have an app that creates variants on the fly and most of the products from our customers are using Options for Weight but there are some merchants that didn’t have a setup for a Weight Option and our app has been basically wiping out the standalone variants for multiple products.

This is an example of a query used to get a product details and the reply using graphqli from the admin dashboard:

Query

query product($id: ID!) {
  product(id: $id) {
    options {
      name
      optionValues {
        name
      }
    }
    variants(first: 100) {
      edges {
        node {
          title
          inventoryItem {
            measurement {
              weight {
                value
                unit
              }
            }
          }
        }
      }
    }
  }
}

Variables

{
  "id": "gid://shopify/Product/8198741557409"
}

Data returned

{
  "data": {
    "product": {
      "options": [
        {
          "name": "Title",
          "optionValues": [
            {
              "name": "Default Title"
            }
          ]
        }
      ],
      "variants": {
        "edges": [
          {
            "node": {
              "sku": "10010101",
              "title": "Default Title",
              "inventoryItem": {
                "measurement": {
                  "weight": {
                    "value": 100,
                    "unit": "GRAMS"
                  }
                }
              }
            }
          }
        ]
      }
    }
  }
}

Mutation

mutation productVariantsBulkCreate($productId: ID!, $variants: [ProductVariantsBulkInput!]!) {
  productVariantsBulkCreate(productId: $productId, variants: $variants, strategy: DEFAULT) {
    productVariants {
      id
      title
      price
      barcode
      taxable
      sku
      product {
        id
        featuredMedia {
          preview {
            image {
              url
            }
          }
        }
      }
      inventoryItem {
        measurement {
          weight {
            unit
            value
          }
        }
      }
      selectedOptions {
        name
        optionValue {
          id
          name
        }
      }
    }
    userErrors {
      field
      message
    }
  }
}

Variables

{
  "productId": "gid://shopify/Product/8198741557409",
  "variants": [
    {
      "price": "0.40",
      "inventoryItem": {
        "tracked": false,
        "sku": "10010101",
        "measurement": {
          "weight": {
            "value": 200,
            "unit": "GRAMS"
          }
        }
      },
      "inventoryPolicy": "CONTINUE",
      "optionValues": [
        {
          "optionName": "Title",
          "name": "200g"
          
        }
      ],
      "taxable": false
    }
  ]
}

Response

{
  "data": {
    "productVariantsBulkCreate": {
      "productVariants": [
        {
          "id": "gid://shopify/ProductVariant/44844161958049",
          "title": "200g",
          "price": "0.40",
          "barcode": null,
          "taxable": false,
          "sku": "10010101",
          "product": {
            "id": "gid://shopify/Product/8198741557409",
            "featuredMedia": {
              "preview": {
                "image": {
                  "url": "https://cdn.shopify.com/s/files/1/0601/1879/4401/products/Jumbo-Oats_d8527fb9-6068-4369-a517-ecbfbb1ffb27.jpg?v=1639517605"
                }
              }
            }
          },
          "inventoryItem": {
            "measurement": {
              "weight": {
                "unit": "GRAMS",
                "value": 200
              }
            }
          },
          "selectedOptions": [
            {
              "name": "Title",
              "optionValue": {
                "id": "gid://shopify/ProductOptionValue/3934731174049",
                "name": "200g"
              }
            }
          ]
        }
      ],
      "userErrors": []
    }
  },
  "extensions": {
    "cost": {
      "requestedQueryCost": 17,
      "actualQueryCost": 17,
      "throttleStatus": {
        "maximumAvailable": 2000,
        "currentlyAvailable": 1983,
        "restoreRate": 100
      }
    }
  }
}

As you can see the initial standalone variant has been wiped out and its no longer there.

Re executing the product query shows that thers only one variant

{
  "data": {
    "product": {
      "options": [
        {
          "name": "Title",
          "optionValues": [
            {
              "name": "200g"
            },
            {
              "name": "Default Title"
            }
          ]
        }
      ],
      "variants": {
        "edges": [
          {
            "node": {
              "title": "200g",
              "sku": "10010101",
              "price": "0.40",
              "inventoryItem": {
                "measurement": {
                  "weight": {
                    "value": 200,
                    "unit": "GRAMS"
                  }
                }
              }
            }
          }
        ]
      }
    }
  },
  "extensions": {
    "cost": {
      "requestedQueryCost": 23,
      "actualQueryCost": 7,
      "throttleStatus": {
        "maximumAvailable": 2000,
        "currentlyAvailable": 1993,
        "restoreRate": 100
      }
    }
  }
}

And the option is forced in the input of the create bulk variants, I tried to specify Weight but it doesn’t accept it. Looks to me that at least if the Title is specified the default strategy for ProductVariantsBulkCreateStrategy should be respected and the standalone variant not deleted.

When creating new variants, could you include the standalone variant as one of the variants in the productVariantsBulkCreate mutation? This would ensure that the standalone variant is not lost.

Yes this is a workaround, but still shouldn’t the underlying issue be fixed in a future API version or even the current one?

What I’m trying to do is report this bug. I’m not sure if this is the right channel for it.

I can for sure flag this to the product team to improve - however I don’t think this is technically broken.

Perhaps I need to explain a bit more what the problem is for you to see how it looks like a bug.

In the following mutation

Strategy field for this mutation is described as

The strategy defines which behavior the mutation should observe, such as whether to keep or delete the standalone variant (when product has only a single or default variant) when creating new variants in bulk.

Where the default strategy is

DEFAULT
The default strategy; keep the standalone variant (when product has only a single or default variant) when creating variants in bulk.

However when there aren’t any options which is considered having a standalone variant exactly as It is described in the DEFAULT description, and creating additional variants in bulk using the operation linked above, the standalone variant is wiped out.

Your proposed solution for this is to include the Standalone variant in the mutation without considering that it implicates sending every field and every value for this variant to avoid losing any details like inventory levels, metafields, etc. Which not only looks like a waste of precious capacity in the graphql allowance but also a problem because even when including this variant a new variant is created with a new id and I think that is enough to cause all the orders that have the default variant sale to be orphan and the new variant will be considered a brand new one.

If it still doesn’t feel like a technical bug please feel free to close this issue as my only intention was to report something that looks like a bug.

Currently, our remedy for this bug is to check if the only option available is Title and if Title only has one value inside of it, which makes us have to call the get product query (1st query we shouldn’t have to do), then if this is the case we create a Weight option with the single variant in it via the Product Option mutation (2nd query we shouldn’t have to make) and then we proceed to call the create bulk variants which avoid wiping out the default variant, or having to include all of it’s details to avoid losing it.

Cheers

Hi again @rafaelsorto

I see how this does seem to be a bug since you’re setting the strategy appropriately to prevent the standalone variant from being erased. Connecting with the product team on this.

Hi again Rafaelsorto,

Our team is still looking into this, it does appear it’s possible this could be a bug on our side, but I’ll update here when I learn more.

I also encountered the same problem