Description
Preconditions
- Magento 2.1.3 EE
Steps to reproduce
I copied my data from 1.7.0.2 using the provided data migration tool. Afterward, when trying to save a category, I would get the error "Something went wrong while saving the category.". Exception log stack trace:
[2016-12-16 19:54:45] report.CRITICAL: Exception: Notice: Undefined offset: 1 in /srv/www/vendor/magento/module-catalog-url-rewrite/Model/ProductUrlRewriteGenerator.php on line 199 in /srv/www/vendor/magento/framework/App/ErrorHandler.php:61
Stack trace:
#0 /srv/www/vendor/magento/module-catalog-url-rewrite/Model/ProductUrlRewriteGenerator.php(199): Magento\Framework\App\ErrorHandler->handler(8, 'Undefined offse...', '/srv/www/vendor...', 199, Array)
#1 /srv/www/vendor/magento/module-catalog-url-rewrite/Model/ProductUrlRewriteGenerator.php(166): Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator->isCategoryProperForGenerating(Object(Magento\Catalog\Model\Category\Interceptor), '1')
#2 /srv/www/vendor/magento/module-catalog-url-rewrite/Model/ProductUrlRewriteGenerator.php(149): Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator->generateForSpecificStoreView('1', Object(Magento\Catalog\Model\ResourceModel\Category\Collection))
#3 /srv/www/vendor/magento/module-catalog-url-rewrite/Model/ProductUrlRewriteGenerator.php(117): Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator->generateForGlobalScope(Object(Magento\Catalog\Model\ResourceModel\Category\Collection))
#4 /srv/www/vendor/magento/module-catalog-url-rewrite/Observer/UrlRewriteHandler.php(80): Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator->generate(Object(Magento\Catalog\Model\Product\Interceptor))
#5 /srv/www/vendor/magento/module-catalog-url-rewrite/Observer/CategoryProcessUrlRewriteSavingObserver.php(58): Magento\CatalogUrlRewrite\Observer\UrlRewriteHandler->generateProductUrlRewrites(Object(Magento\Catalog\Model\Category\Interceptor))
#6 /srv/www/vendor/magento/framework/Event/Invoker/InvokerDefault.php(73): Magento\CatalogUrlRewrite\Observer\CategoryProcessUrlRewriteSavingObserver->execute(Object(Magento\Framework\Event\Observer))
#7 /srv/www/vendor/magento/framework/Event/Invoker/InvokerDefault.php(61): Magento\Framework\Event\Invoker\InvokerDefault->_callObserverMethod(Object(Magento\CatalogUrlRewrite\Observer\CategoryProcessUrlRewriteSavingObserver), Object(Magento\Framework\Event\Observer))
#8 /srv/www/vendor/magento/module-staging/Model/Event/Manager.php(97): Magento\Framework\Event\Invoker\InvokerDefault->dispatch(Array, Object(Magento\Framework\Event\Observer))
#9 /srv/www/var/generation/Magento/Staging/Model/Event/Manager/Proxy.php(95): Magento\Staging\Model\Event\Manager->dispatch('catalog_categor...', Array)
#10 /srv/www/vendor/magento/framework/Model/AbstractModel.php(802): Magento\Staging\Model\Event\Manager\Proxy->dispatch('catalog_categor...', Array)
#11 /srv/www/vendor/magento/module-catalog/Model/Category.php(1077): Magento\Framework\Model\AbstractModel->afterSave()
#12 /srv/www/var/generation/Magento/Catalog/Model/Category/Interceptor.php(583): Magento\Catalog\Model\Category->afterSave()
#13 /srv/www/vendor/magento/framework/EntityManager/Observer/AfterEntitySave.php(34): Magento\Catalog\Model\Category\Interceptor->afterSave()
#14 /srv/www/vendor/magento/framework/Event/Invoker/InvokerDefault.php(73): Magento\Framework\EntityManager\Observer\AfterEntitySave->execute(Object(Magento\Framework\Event\Observer))
#15 /srv/www/vendor/magento/framework/Event/Invoker/InvokerDefault.php(61): Magento\Framework\Event\Invoker\InvokerDefault->_callObserverMethod(Object(Magento\Framework\EntityManager\Observer\AfterEntitySave), Object(Magento\Framework\Event\Observer))
#16 /srv/www/vendor/magento/module-staging/Model/Event/Manager.php(97): Magento\Framework\Event\Invoker\InvokerDefault->dispatch(Array, Object(Magento\Framework\Event\Observer))
#17 /srv/www/var/generation/Magento/Staging/Model/Event/Manager/Proxy.php(95): Magento\Staging\Model\Event\Manager->dispatch('magento_catalog...', Array)
#18 /srv/www/vendor/magento/framework/EntityManager/EventManager.php(51): Magento\Staging\Model\Event\Manager\Proxy->dispatch('magento_catalog...', Array)
#19 /srv/www/vendor/magento/module-staging/Model/Operation/Update.php(208): Magento\Framework\EntityManager\EventManager->dispatchEntityEvent('Magento\\Catalog...', 'save_after', Array)
#20 /srv/www/vendor/magento/framework/EntityManager/EntityManager.php(87): Magento\Staging\Model\Operation\Update->execute(Object(Magento\Catalog\Model\Category\Interceptor), Array)
#21 /srv/www/vendor/magento/module-catalog/Model/ResourceModel/Category.php(1025): Magento\Framework\EntityManager\EntityManager->save(Object(Magento\Catalog\Model\Category\Interceptor))
#22 /srv/www/vendor/magento/framework/Interception/Interceptor.php(74): Magento\Catalog\Model\ResourceModel\Category->save(Object(Magento\Catalog\Model\Category\Interceptor))
#23 /srv/www/vendor/magento/framework/Interception/Chain/Chain.php(70): Magento\Catalog\Model\ResourceModel\Category\Interceptor->___callParent('save', Array)
#24 /srv/www/vendor/magento/framework/Interception/Chain/Chain.php(63): Magento\Framework\Interception\Chain\Chain->invokeNext('Magento\\Catalog...', 'save', Object(Magento\Catalog\Model\ResourceModel\Category\Interceptor), Array, 'catalogsearchFu...')
#25 /srv/www/vendor/magento/module-catalog-search/Model/Indexer/Fulltext/Plugin/Category.php(43): Magento\Framework\Interception\Chain\Chain->Magento\Framework\Interception\Chain\{closure}(Object(Magento\Catalog\Model\Category\Interceptor))
#26 /srv/www/vendor/magento/module-catalog-search/Model/Indexer/Fulltext/Plugin/Category.php(29): Magento\CatalogSearch\Model\Indexer\Fulltext\Plugin\Category->addCommitCallback(Object(Magento\Catalog\Model\ResourceModel\Category\Interceptor), Object(Closure), Object(Magento\Catalog\Model\Category\Interceptor))
#27 /srv/www/vendor/magento/framework/Interception/Chain/Chain.php(67): Magento\CatalogSearch\Model\Indexer\Fulltext\Plugin\Category->aroundSave(Object(Magento\Catalog\Model\ResourceModel\Category\Interceptor), Object(Closure), Object(Magento\Catalog\Model\Category\Interceptor))
#28 /srv/www/vendor/magento/framework/Interception/Interceptor.php(138): Magento\Framework\Interception\Chain\Chain->invokeNext('Magento\\Catalog...', 'save', Object(Magento\Catalog\Model\ResourceModel\Category\Interceptor), Array, 'clean_cache')
#29 /srv/www/vendor/magento/framework/App/Cache/FlushCacheByTags.php(60): Magento\Catalog\Model\ResourceModel\Category\Interceptor->Magento\Framework\Interception\{closure}(Object(Magento\Catalog\Model\Category\Interceptor))
#30 /srv/www/vendor/magento/framework/Interception/Interceptor.php(142): Magento\Framework\App\Cache\FlushCacheByTags->aroundSave(Object(Magento\Catalog\Model\ResourceModel\Category\Interceptor), Object(Closure), Object(Magento\Catalog\Model\Category\Interceptor))
#31 /srv/www/var/generation/Magento/Catalog/Model/ResourceModel/Category/Interceptor.php(364): Magento\Catalog\Model\ResourceModel\Category\Interceptor->___callPlugins('save', Array, Array)
#32 /srv/www/vendor/magento/framework/Model/AbstractModel.php(631): Magento\Catalog\Model\ResourceModel\Category\Interceptor->save(Object(Magento\Catalog\Model\Category\Interceptor))
#33 /srv/www/vendor/magento/framework/Interception/Interceptor.php(146): Magento\Framework\Model\AbstractModel->save()
#34 /srv/www/var/generation/Magento/Catalog/Model/Category/Interceptor.php(1534): Magento\Catalog\Model\Category\Interceptor->___callPlugins('save', Array, Array)
#35 /srv/www/vendor/magento/module-catalog/Controller/Adminhtml/Category/Save.php(203): Magento\Catalog\Model\Category\Interceptor->save()
#36 /srv/www/var/generation/Magento/Catalog/Controller/Adminhtml/Category/Save/Interceptor.php(24): Magento\Catalog\Controller\Adminhtml\Category\Save->execute()
#37 /srv/www/vendor/magento/framework/App/Action/Action.php(102): Magento\Catalog\Controller\Adminhtml\Category\Save\Interceptor->execute()
#38 /srv/www/vendor/magento/module-backend/App/AbstractAction.php(226): Magento\Framework\App\Action\Action->dispatch(Object(Magento\Framework\App\Request\Http))
#39 /srv/www/vendor/magento/framework/Interception/Interceptor.php(74): Magento\Backend\App\AbstractAction->dispatch(Object(Magento\Framework\App\Request\Http))
#40 /srv/www/vendor/magento/framework/Interception/Chain/Chain.php(70): Magento\Catalog\Controller\Adminhtml\Category\Save\Interceptor->___callParent('dispatch', Array)
#41 /srv/www/vendor/magento/framework/Interception/Chain/Chain.php(63): Magento\Framework\Interception\Chain\Chain->invokeNext('Magento\\Catalog...', 'dispatch', Object(Magento\Catalog\Controller\Adminhtml\Category\Save\Interceptor), Array, 'adminAuthentica...')
#42 /srv/www/vendor/magento/module-backend/App/Action/Plugin/Authentication.php(143): Magento\Framework\Interception\Chain\Chain->Magento\Framework\Interception\Chain\{closure}(Object(Magento\Framework\App\Request\Http))
#43 /srv/www/vendor/magento/framework/Interception/Chain/Chain.php(67): Magento\Backend\App\Action\Plugin\Authentication->aroundDispatch(Object(Magento\Catalog\Controller\Adminhtml\Category\Save\Interceptor), Object(Closure), Object(Magento\Framework\App\Request\Http))
#44 /srv/www/vendor/magento/framework/Interception/Chain/Chain.php(63): Magento\Framework\Interception\Chain\Chain->invokeNext('Magento\\Catalog...', 'dispatch', Object(Magento\Catalog\Controller\Adminhtml\Category\Save\Interceptor), Array, 'log')
#45 /srv/www/vendor/magento/module-logging/App/Action/Plugin/Log.php(69): Magento\Framework\Interception\Chain\Chain->Magento\Framework\Interception\Chain\{closure}(Object(Magento\Framework\App\Request\Http))
#46 /srv/www/vendor/magento/framework/Interception/Chain/Chain.php(67): Magento\Logging\App\Action\Plugin\Log->aroundDispatch(Object(Magento\Catalog\Controller\Adminhtml\Category\Save\Interceptor), Object(Closure), Object(Magento\Framework\App\Request\Http))
#47 /srv/www/vendor/magento/framework/Interception/Interceptor.php(138): Magento\Framework\Interception\Chain\Chain->invokeNext('Magento\\Catalog...', 'dispatch', Object(Magento\Catalog\Controller\Adminhtml\Category\Save\Interceptor), Array, 'adminMassaction...')
#48 /srv/www/vendor/magento/module-backend/App/Action/Plugin/MassactionKey.php(33): Magento\Catalog\Controller\Adminhtml\Category\Save\Interceptor->Magento\Framework\Interception\{closure}(Object(Magento\Framework\App\Request\Http))
#49 /srv/www/vendor/magento/framework/Interception/Interceptor.php(142): Magento\Backend\App\Action\Plugin\MassactionKey->aroundDispatch(Object(Magento\Catalog\Controller\Adminhtml\Category\Save\Interceptor), Object(Closure), Object(Magento\Framework\App\Request\Http))
#50 /srv/www/var/generation/Magento/Catalog/Controller/Adminhtml/Category/Save/Interceptor.php(65): Magento\Catalog\Controller\Adminhtml\Category\Save\Interceptor->___callPlugins('dispatch', Array, Array)
#51 /srv/www/vendor/magento/framework/App/FrontController.php(55): Magento\Catalog\Controller\Adminhtml\Category\Save\Interceptor->dispatch(Object(Magento\Framework\App\Request\Http))
#52 /srv/www/vendor/magento/framework/Interception/Interceptor.php(74): Magento\Framework\App\FrontController->dispatch(Object(Magento\Framework\App\Request\Http))
#53 /srv/www/vendor/magento/framework/Interception/Chain/Chain.php(70): Magento\Framework\App\FrontController\Interceptor->___callParent('dispatch', Array)
#54 /srv/www/vendor/magento/framework/Interception/Interceptor.php(138): Magento\Framework\Interception\Chain\Chain->invokeNext('Magento\\Framewo...', 'dispatch', Object(Magento\Framework\App\FrontController\Interceptor), Array, 'install')
#55 /srv/www/vendor/magento/framework/Module/Plugin/DbStatusValidator.php(69): Magento\Framework\App\FrontController\Interceptor->Magento\Framework\Interception\{closure}(Object(Magento\Framework\App\Request\Http))
#56 /srv/www/vendor/magento/framework/Interception/Interceptor.php(142): Magento\Framework\Module\Plugin\DbStatusValidator->aroundDispatch(Object(Magento\Framework\App\FrontController\Interceptor), Object(Closure), Object(Magento\Framework\App\Request\Http))
#57 /srv/www/var/generation/Magento/Framework/App/FrontController/Interceptor.php(26): Magento\Framework\App\FrontController\Interceptor->___callPlugins('dispatch', Array, Array)
#58 /srv/www/vendor/magento/framework/App/Http.php(135): Magento\Framework\App\FrontController\Interceptor->dispatch(Object(Magento\Framework\App\Request\Http))
#59 /srv/www/vendor/magento/framework/App/Bootstrap.php(258): Magento\Framework\App\Http->launch()
#60 /srv/www/pub/index.php(37): Magento\Framework\App\Bootstrap->run(Object(Magento\Framework\App\Http))
#61 {main} [] []
The structure is a bit different (an EE difference I am guessing), but the method with the error is just like this one: https://github.com/magento/magento2/blob/develop/app/code/Magento/CatalogUrlRewrite/Model/ProductScopeRewriteGenerator.php#L166
list(, $rootCategoryId)
fails with undefined offset because $category->getParentIds()
returns an empty array. It took me quite awhile, but I eventually found the cause. For each product in the category saved, it will call this isCategoryProperForGenerating
method for each category that product happens to be in.
It turns out I have several products assigned to the Root Catalog category. No idea why that is, but that's how it was in M1--the very first entry in magento1.catalog_category_product
is our first product assigned to category_id 1. $category->getParentId()
for this product is 0
, so it passes the != TREE_ROOT_ID
(AKA 1) check and goes on to the list
call, which breaks because the Root Catalog category has no parents. If it also checks != ROOT_CATEGORY_ID
(AKA 0), it should work.
Expected result
- "You saved the category."
Actual result
- "Something went wrong while saving the category."
Suggested solution
In vendor/magento/module-catalog-url-rewrite/Model/ProductUrlRewriteGenerator.php
, change line 194 to
if ($category->getParentId() != \Magento\Catalog\Model\Category::TREE_ROOT_ID
&& $category->getParentId() != \Magento\Catalog\Model\Category::ROOT_CATEGORY_ID
) {
But in order to not modify core code myself, I'll just be clearing out the Root Category assignments:
delete from catalog_category_product where category_id = 1;