magento2: Magento EE 2.1.0 'Configurable product "%1" does not have sub-products'

Steps to reproduce

  1. Create configurable product with no simple products associated
  2. Associate product to category
  3. Save category

Actual result

  1. Exception: Configurable product “%1” does not have sub-products

The problem is with the method, cause the configurable product has no child:

<?php
namespace Magento\ConfigurableProduct\Pricing\Price;

/**
     * @param \Magento\Framework\Pricing\SaleableInterface|\Magento\Catalog\Model\Product $product
     * @return float
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    public function resolvePrice(\Magento\Framework\Pricing\SaleableInterface $product)
    {
        $price = null;
        foreach ($this->configurable->getUsedProducts($product) as $subProduct) {
            $productPrice = $this->priceResolver->resolvePrice($subProduct);
            $price = $price ? min($price, $productPrice) : $productPrice;
        }
        if ($price === null) {
            throw new \Magento\Framework\Exception\LocalizedException(
                __('Configurable product "%1" does not have sub-products', $product->getSku())
            );
        }
        return (float)$price;
    }

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 9
  • Comments: 47 (10 by maintainers)

Commits related to this issue

Most upvoted comments

I don’t know why @magento-admin is not replying to this problem. How can we prefer our customer’s to use such a system where lots of bugs are still there.

Thanks

I am having this issue in 2.1.1.

It is happening when the first configuration simple product is 0 qty OR set as ‘out of stock’. The exception is not occurring for other configurations that are not the FIRST simple product.

To replicate, create configurable product, with more than one associated simple product. Set qty for the first simple product to zero or out of stock.

Same Problem here. (2.1.2)

I’ve submitted a Pull Request for this issue, hopefully it’s accepted and incorporated into the next version. For now, you can see the #7030 pull request and incorporate the changes into your own magento version. If you do, test thoroughly, and know that it’s entirely at your own risk. My concern is that this will create performance issues on stores with large numbers of configurable products and options.

tl;dr The array of subproducts is being limited to the first enabled product by the SQL generated in the LinkedProductSelectBuilders.

I’ve been experimenting with debugging this, because it’s a bit of a priority to have low or no stock products within my configurables.

The sizeof() $this->getConfigurableOptionsProvider()->getProducts($product) in vendor/magento/module-configurable-product/Pricing/Price/ConfigurableOptionsProvider.php is returning 1 when my first simple product is quantity 0 but disabled. Hence, it returns only the first enabled sub-product, not all sub-products as it should.

Diving deeper, Magento\ConfigurableProduct\Pricing\Price\ConfigurableOptionsProvider->getProducts() line 79

$productIds = $this->resource->getConnection()->fetchCol( '(' . implode(') UNION (', $this->linkedProductSelectBuilder->build($product->getId())) . ')' );

creates SQL that looks like this:

‘SELECT child.entity_id FROM catalog_product_entity AS parent INNER JOIN catalog_product_relation AS link ON link.parent_id = parent.entity_id INNER JOIN catalog_product_entity AS child ON child.entity_id = link.child_id INNER JOIN catalog_product_entity_decimal AS t ON t.entity_id = child.entity_id WHERE (parent.entity_id = ‘81’ ) AND (t.attribute_id = ‘77’) AND (t.value IS NOT NULL) AND (t.store_id = 0) ORDER BY t.value ASC LIMIT 1) UNION (SELECT child.entity_id FROM catalog_product_entity AS parent INNER JOIN catalog_product_relation AS link ON link.parent_id = parent.entity_id INNER JOIN catalog_product_entity AS child ON child.entity_id = link.child_id INNER JOIN catalog_product_entity_decimal AS t ON t.entity_id = child.entity_id LEFT JOIN catalog_product_entity_datetime AS special_from ON t.entity_id = special_from.entity_id AND special_from.attribute_id = ‘79’ LEFT JOIN catalog_product_entity_datetime AS special_to ON t.entity_id = special_to.entity_id AND special_to.attribute_id = ‘80’ WHERE (parent.entity_id = ‘81’ ) AND (t.attribute_id = ‘78’) AND (t.value IS NOT NULL) AND (special_from.value IS NULL OR DATE(special_from.value) <= ‘2016-10-06’) AND (special_to.value IS NULL OR DATE(special_to.value) >= ‘2016-10-06’) AND (t.store_id = 0) ORDER BY t.value ASC LIMIT 1) UNION (SELECT child.entity_id FROM catalog_product_entity AS parent INNER JOIN catalog_product_relation AS link ON link.parent_id = parent.entity_id INNER JOIN catalog_product_entity AS child ON child.entity_id = link.child_id INNER JOIN catalog_product_entity_tier_price AS t ON t.entity_id = child.entity_id WHERE (parent.entity_id = ‘81’ ) AND (t.all_groups = 1 OR customer_group_id = 0) AND (t.qty = 1) AND (t.website_id = 0) ORDER BY t.value ASC LIMIT 1) UNION (SELECT child.entity_id FROM catalog_product_entity AS parent INNER JOIN catalog_product_relation AS link ON link.parent_id = parent.entity_id INNER JOIN catalog_product_entity AS child ON child.entity_id = link.child_id INNER JOIN catalog_product_index_price AS t ON t.entity_id = child.entity_id WHERE (parent.entity_id = ‘81’ ) AND (t.website_id = ‘1’) AND (t.customer_group_id = 0) ORDER BY t.min_price ASC LIMIT 1) UNION (SELECT child.entity_id FROM catalog_product_entity AS parent INNER JOIN catalog_product_relation AS link ON link.parent_id = parent.entity_id INNER JOIN catalog_product_entity AS child ON child.entity_id = link.child_id INNER JOIN catalogrule_product_price AS t ON t.product_id = child.entity_id WHERE (parent.entity_id = ‘81’ ) AND (t.website_id = ‘1’) AND (t.customer_group_id = 0) AND (t.rule_date = ‘2016-10-06’) ORDER BY t.rule_price ASC LIMIT 1’

This giant SQL statement returns an array like below when the first simple product in my configurable has a quantity of 0 but is disabled. It does not represent all simple products in my configurable, or even just the ones with quantity, what it shows is the entity_ids of the first two simple products in the configurable product. This is incorrect.

( [0] => 1 [1] => 2 )

When the first simple product is enabled with a quantity of 0, the system crashes with the error in question and the $productIds array looks like this. I.e. it shows only the first simple product entity_id in the configurable product even though it’s out of stock:

( [0] => 1 )

The error is thrown because

$this->products[$product->getId()] = $this->collectionFactory->create() ->addAttributeToSelect(['price', 'special_price']) ->addIdFilter($productIds);

is null. It’s filtering everything by the faulty $productIds array, which isn’t representative of the configurable products options.

Removing ->limit(1) or setting it to PHP_INT_MAX from LinkedProductSelectBuilderBySpecialPrice, LinkedProductSelectBuilderByBasePrice and LinkedProductSelectBuilderByTierPrice generates the correct full array of $productIds. I have no idea what ramifications this might have for other parts of Magento.

Hi guys, try this: check the stock status for each subproduct. At least one should be “In Stock”, otherwise you get this error. This worked for me.

Updating catalog_product_relation table from catalog_product_super_link resolved this issue.

Hi @oserediuk , I have updated the step to reproduce, currently working on a EE 2.1.1 and facing the same issue. Thanks

I installed Magento CE 2.1.2 with composer and I can’t use this commit. I tried manually modifying the patched files and it completely broke my installation. Can you guys publish the next release with this patch or at least a patch for v2.1.2 because the whole CMS is unusable with this bug.

@SKovbel I couldn’t find where to put your temporary fix. Can you explain further what files should we modify?

Hi TienYiChi, Now sell out of the FIRST product option (the associated simple product with the lowest id), does this still work for you?