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

Created on 22 Jul 2016  Â·  47Comments  Â·  Source: magento/magento2

Steps to reproduce

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

    Actual result

  4. 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;
    }

Catalog Ready for Work bug report

Most helpful comment

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

All 47 comments

@etessari correct me if I'm wrong, but configurable products are meant to have sub-products (aka Child). So what you are describing is not a bug, just the program letting you know that a configurable product must have sub-products.

Hello @etessari ! I cannot reproduce your issue. If I create configurable product without sub-product, it is saved successfully as simple without exception. It is normal behavior. Configurable product without sub-product becomes a simple product.

Could you clarify steps to reproduce or add some details?

I get this error all of a sudden when I try to update from 2.0.8 to 2.1.0

My configurable products have sub-products (simple products) assigned but still get this error in 2.1.1.
In 2.1.0 this issue is not present in my installation.

Hi @etessari ,
as @oserediuk said , if you create configurable product without configuration it is saved as simple. Please provide all fields you fill for this product when you encountered this error.
@kanduvisla ,
all configurable products are editable and has correct data after upgrading Magento from 2.0.8 to 2.1.0.
Please provide more detailed steps to reproduce: when you have this error, what fields configurable product has, does product have multistore attributes data, etc.

Thanks,

I'm also seeing this issue with Magento 2.1.1, will report if I have extra information available how to fix the issue.

I am using Magento 2.1.1 version and facing the same issue.

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.

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

Got the same issue as well, we've upgrade from 2.0.7 to 2.1.1, on 2.1.0 it was working.

In vendor/magento/module-configurable-product/Pricing/Price/ConfigurableOptionsProvider.php:

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

The collection has a size when using ->getSize() on the collection but the iterator doesn't work.

mysql> SELECT `e`.* FROM `catalog_product_entity` AS `e` WHERE (`e`.`entity_id` IN('387967', '387969')) AND (e.created_in <= 1) AND (e.updated_in > 1);
+--------+-----------+------------+------------+------------------+---------+----------+-------------+------------------+---------------------+---------------------+
| row_id | entity_id | created_in | updated_in | attribute_set_id | type_id | sku      | has_options | required_options | created_at          | updated_at          |
+--------+-----------+------------+------------+------------------+---------+----------+-------------+------------------+---------------------+---------------------+
| 387967 |    387967 |          1 | 2147483647 |               15 | simple  | eg2819 |           0 |                0 | 2016-07-07 13:54:42 | 2016-09-26 10:44:54 |
| 387969 |    387969 |          1 | 2147483647 |               15 | simple  | eg2821 |           0 |                0 | 2016-07-07 13:54:48 | 2016-09-26 10:44:54 |
+--------+-----------+------------+------------+------------------+---------+----------+-------------+------------------+---------------------+---------------------+

The collection isn't loading the products so the iterator isn't working thus the price is not getting set, I can't work out what is wrong if I do will update.

If any one found the solution to above problem than please let me know.
Thanks in advance.

I am experiencing the same issue as @staffrob, CE 2.1.1 . Disabling the simple products that are out of stock in the configurable product's "Configurations" area resolves this, but this is obviously not a sustainable solution long-term. Screenshot below for where that option is.
screen shot 2016-09-28 at 5 21 40 pm

Can confirm the same problem as @staffrob in 2.1.1

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

Updating catalog_product_relation table from catalog_product_super_link resolved this issue.

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.

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

@staffrob good point, I did what you said and it crashed again...
sorry I didn't notice you already mentioned this case far above

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.

@nissablagojevic -- Can you give a more specific "fix" for this? Looking around, I can't find the ->limit(1) or the LinkedProductSelect... functions.

@nissablagojevic Is there any more progress on a fix for this issue? Spent days wondering why my products were not showing up and now finally figured out this was the cause.

@nissablagojevic seconding what @rsetht and @danny3388 said. Where did you find limit(1)? Is it in the SQL tables and if so which 1?

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.

I'm having this issue as well on magento 2.1.2

The error is no longer showing up on category or product page.
When Mview enabled/indexer set to Update by Schedule:
on product page, there is the configurable option associated with the simple product out of stock.
And if I select it it won't show Out of Stock status in price box.
If I add it to cart it will tell 'You need to choose options for your item.'.
I wasn't looking forward to debug Magento 2 today.

Indexer set to Update on Save won't work either as described above.
I'm on Magento 2.1.2 in developer mode.
I've applied the fixes in the 5 files from @timneill and @paales

Just experienced this issue.

I have a custom cronjob. The cronjob is responsible for looping through all the products and generate a feed. This issue Configurable product "321" does not have sub-products was the result of the cronjob. Meaning the cronjob terminated, and the feed was not created.

i also have same problem . let me know if any one find solution.

Hello.
I have this same problem, please if you find a soluction let me know, i have magento 2.1.2 in developer mode.
Regards.

Quick fix with observing catalog_block_product_list_collection event

/**
 * Local/Catalog/etc/frontend/events.xml
 *
 * <?xml version="1.0"?>
 * <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  *xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
 *    <event name="catalog_block_product_list_collection">
 *        <observer name="local_catalog_block_product_list_collection" instance="Local\Catalog\Observer\Collection" />
 *    </event>
 * </config>
 **/
namespace Local\Catalog\Observer;


class Collection implements \Magento\Framework\Event\ObserverInterface
{
    /**
     * Collection constructor.
     */
    public function __construct()
    {

    }

    /**
     * @param \Magento\Framework\Event\Observer $observer
     */
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        /** @var \Magento\Catalog\Model\ResourceModel\Category\Collection $collection */
        $collection = $observer->getData('collection');

        $parts = $collection->getSelect()->getPart(\Zend_Db_Select::FROM);
        if (isset($parts['superlink'])) {
            return $this;
        }

        $superlinkExpr = new \Zend_Db_Expr("
            (
                SELECT `parent_id`, COUNT(*) AS `child_cnt` 
                  FROM `{$collection->getTable('catalog_product_super_link')}` AS `superlink`
                 GROUP BY `parent_id` 
            )
        ");

        $collection->getSelect()->joinLeft(
            ['superlink' => $superlinkExpr],
            'e.entity_id = superlink.parent_id',
            []
        );

        $collection->getSelect()->where("e.type_id != 'configurable' OR superlink.child_cnt > 0");

        return $this;
    }
}

Hi @etessari

We already have related ticket MAGETWO-60483 and the fix will be delivered soon.
Thanks.

Same problem in 2.1.2.

This happens when a configurable product has out of stock sub-products.

As @nissablagojevic said, I had to disable out of stock product to do working.

@shiftedreality Any ETA on an official fix?

Have same problem, please fix

have same problem

Same Problem here. (2.1.2)

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

Hi @etessari

Fix for this issue was merged into develop branch https://github.com/magento/magento2/commit/1e78fe2e37af0012b7f60b29c658221b8ab8467b

@shiftedreality Is this fix safe as is for a 2.1.2 production environment with a live website or do some modifications need to be made?

We tested with 2.1.2 CE in production environment and it worked perfectly.

From: Ctucker9233 notifications@github.com
Reply-To: magento/magento2 reply@reply.github.com
Date: Thursday, December 8, 2016 at 1:34 PM
To: magento/magento2 magento2@noreply.github.com
Cc: Ali Ahmed ali@imaginemage.com, Comment comment@noreply.github.com
Subject: Re: [magento/magento2] Magento EE 2.1.0 'Configurable product "%1" does not have sub-products' (#5762)

@shiftedrealityhttps://github.com/shiftedreality Is this fix safe as is for a 2.1.2 production environment with a live website or do some modifications need to be made?

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHubhttps://github.com/magento/magento2/issues/5762#issuecomment-265817268, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AUEf3de2Q0ncizanMYcDNU0VfBB2WQtiks5rGE22gaJpZM4JSu05.

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.

Does 2.1.3 solved this?

Yes, solved in 2.1.3

Sent from my iPhone

On 18 Jan 2017, at 3:11 pm, PY Yick notifications@github.com wrote:

Does 2.1.3 solved this?

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.

2.1.3 solved for me as well the problem

Solved in 2.1.3. Thanks.

2017-01-18 7:48 GMT+01:00 PhiIipp notifications@github.com:

2.1.3 solved for me as well the problem

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/magento/magento2/issues/5762#issuecomment-273397715,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAzWKeaQXwU6iwYPqAXeDxD_93aRbwAFks5rTbXNgaJpZM4JSu05
.

Closed.

Was this page helpful?
0 / 5 - 0 ratings