Skip to content

Magento EE 2.1.0 'Configurable product "%1" does not have sub-products' #5762

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
etessari opened this issue Jul 22, 2016 · 47 comments
Closed
Labels
bug report Component: Catalog Issue: Ready for Work Gate 4. Acknowledged. Issue is added to backlog and ready for development

Comments

@etessari
Copy link

etessari commented Jul 22, 2016

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;
    }
@Ctucker9233
Copy link

@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.

@oserediuk
Copy link
Contributor

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?

@kanduvisla
Copy link
Contributor

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

@jibrandlr
Copy link

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.

@NadiyaS
Copy link
Contributor

NadiyaS commented Aug 31, 2016

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,

@paales
Copy link
Contributor

paales commented Aug 31, 2016

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

@sanjayjethva
Copy link

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

@staffrob
Copy link

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.

@etessari
Copy link
Author

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

@jzahedieh
Copy link

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.

@sanjayjethva
Copy link

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

@nissablagojevic
Copy link

nissablagojevic commented Sep 28, 2016

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

@etessari etessari changed the title Magento 2.1.0 'Configurable product "%1" does not have sub-products' Magento EE 2.1.0 'Configurable product "%1" does not have sub-products' Sep 28, 2016
@cuiyang000
Copy link

Can confirm the same problem as @staffrob in 2.1.1

@sanjayjethva
Copy link

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

@sivaschenko
Copy link
Member

Updating catalog_product_relation table from catalog_product_super_link resolved this issue.

@TienYiChi
Copy link

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.

@staffrob
Copy link

staffrob commented Oct 3, 2016

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

@TienYiChi
Copy link

TienYiChi commented Oct 4, 2016

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

@nissablagojevic
Copy link

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.

@Ctucker9233
Copy link

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

@timneill
Copy link

@nissablagojevic
Copy link

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.

@ooples
Copy link

ooples commented Nov 7, 2016

I'm having this issue as well on magento 2.1.2

@daniel-ifrim
Copy link

daniel-ifrim commented Nov 8, 2016

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

@petterkj
Copy link
Contributor

petterkj commented Nov 9, 2016

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.

@bharatgunani
Copy link

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

@panchomuniz
Copy link

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.

@SKovbel
Copy link

SKovbel commented Nov 25, 2016

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

@shiftedreality
Copy link
Member

Hi @etessari

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

@sergiojovanig
Copy link

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 shiftedreality added the Issue: Ready for Work Gate 4. Acknowledged. Issue is added to backlog and ready for development label Nov 28, 2016
@lahdekorpi
Copy link

@shiftedreality Any ETA on an official fix?

@Koc
Copy link

Koc commented Dec 2, 2016

Have same problem, please fix

@sijad
Copy link

sijad commented Dec 4, 2016

have same problem

@imgali
Copy link

imgali commented Dec 4, 2016

Same Problem here. (2.1.2)

@kh-badep
Copy link

kh-badep commented Dec 5, 2016

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

@shiftedreality
Copy link
Member

Hi @etessari

Fix for this issue was merged into develop branch 1e78fe2

@Ctucker9233
Copy link

@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?

@imgali
Copy link

imgali commented Dec 8, 2016 via email

@kh-badep
Copy link

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.

@pyyick
Copy link

pyyick commented Jan 18, 2017

Does 2.1.3 solved this?

@staffrob
Copy link

staffrob commented Jan 18, 2017 via email

@PhiIipp
Copy link

PhiIipp commented Jan 18, 2017

2.1.3 solved for me as well the problem

@sergiojovanig
Copy link

sergiojovanig commented Jan 18, 2017 via email

@shiftedreality
Copy link
Member

Closed.

magento-engcom-team pushed a commit that referenced this issue Jun 5, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug report Component: Catalog Issue: Ready for Work Gate 4. Acknowledged. Issue is added to backlog and ready for development
Projects
None yet
Development

No branches or pull requests