magento2: Cannot save attribute

Preconditions

  1. Have an attribute with a source model Magento\Eav\Model\Entity\Attribute\Source\Boolean
  2. Have it’s frontend_input with “select”.

Steps to reproduce

  1. Go in backend and try to save the attribute

Expected result

  1. The attribute must be saved with success

Actual result

  1. Error 500 :
1 exception(s):
Exception #0 (Exception): Notice: Undefined index: value in /var/www/preprod/vendor/magento/module-catalog/Controller/Adminhtml/Product/Attribute/Validate.php on line 155

Exception #0 (Exception): Notice: Undefined index: value in /var/www/preprod/vendor/magento/module-catalog/Controller/Adminhtml/Product/Attribute/Validate.php on line 155
#0 /var/www/preprod/vendor/magento/module-catalog/Controller/Adminhtml/Product/Attribute/Validate.php(155): Magento\Framework\App\ErrorHandler->handler(8, 'Undefined index...', '/var/www/prepro...', 155, Array)
#1 /var/www/preprod/vendor/magento/module-catalog/Controller/Adminhtml/Product/Attribute/Validate.php(108): Magento\Catalog\Controller\Adminhtml\Product\Attribute\Validate->checkUniqueOption(Object(Magento\Framework\DataObject), Array)
#2 /var/www/preprod/var/generation/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate/Interceptor.php(24): Magento\Catalog\Controller\Adminhtml\Product\Attribute\Validate->execute()
#3 /var/www/preprod/vendor/magento/framework/App/Action/Action.php(102): Magento\Catalog\Controller\Adminhtml\Product\Attribute\Validate\Interceptor->execute()
#4 /var/www/preprod/vendor/magento/module-backend/App/AbstractAction.php(226): Magento\Framework\App\Action\Action->dispatch(Object(Magento\Framework\App\Request\Http))
#5 /var/www/preprod/vendor/magento/module-catalog/Controller/Adminhtml/Product/Attribute.php(79): Magento\Backend\App\AbstractAction->dispatch(Object(Magento\Framework\App\Request\Http))
#6 /var/www/preprod/vendor/magento/framework/Interception/Interceptor.php(74): Magento\Catalog\Controller\Adminhtml\Product\Attribute->dispatch(Object(Magento\Framework\App\Request\Http))
#7 /var/www/preprod/vendor/magento/framework/Interception/Chain/Chain.php(70): Magento\Catalog\Controller\Adminhtml\Product\Attribute\Validate\Interceptor->___callParent('dispatch', Array)
#8 /var/www/preprod/vendor/magento/framework/Interception/Chain/Chain.php(63): Magento\Framework\Interception\Chain\Chain->invokeNext('Magento\\Catalog...', 'dispatch', Object(Magento\Catalog\Controller\Adminhtml\Product\Attribute\Validate\Interceptor), Array, 'adminAuthentica...')
#9 /var/www/preprod/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))
#10 /var/www/preprod/vendor/magento/framework/Interception/Chain/Chain.php(67): Magento\Backend\App\Action\Plugin\Authentication->aroundDispatch(Object(Magento\Catalog\Controller\Adminhtml\Product\Attribute\Validate\Interceptor), Object(Closure), Object(Magento\Framework\App\Request\Http))
#11 /var/www/preprod/vendor/magento/framework/Interception/Interceptor.php(138): Magento\Framework\Interception\Chain\Chain->invokeNext('Magento\\Catalog...', 'dispatch', Object(Magento\Catalog\Controller\Adminhtml\Product\Attribute\Validate\Interceptor), Array, 'adminMassaction...')
#12 /var/www/preprod/vendor/magento/module-backend/App/Action/Plugin/MassactionKey.php(33): Magento\Catalog\Controller\Adminhtml\Product\Attribute\Validate\Interceptor->Magento\Framework\Interception\{closure}(Object(Magento\Framework\App\Request\Http))
#13 /var/www/preprod/vendor/magento/framework/Interception/Interceptor.php(142): Magento\Backend\App\Action\Plugin\MassactionKey->aroundDispatch(Object(Magento\Catalog\Controller\Adminhtml\Product\Attribute\Validate\Interceptor), Object(Closure), Object(Magento\Framework\App\Request\Http))
#14 /var/www/preprod/var/generation/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate/Interceptor.php(39): Magento\Catalog\Controller\Adminhtml\Product\Attribute\Validate\Interceptor->___callPlugins('dispatch', Array, Array)
#15 /var/www/preprod/vendor/magento/framework/App/FrontController.php(55): Magento\Catalog\Controller\Adminhtml\Product\Attribute\Validate\Interceptor->dispatch(Object(Magento\Framework\App\Request\Http))
#16 /var/www/preprod/vendor/magento/framework/Interception/Interceptor.php(74): Magento\Framework\App\FrontController->dispatch(Object(Magento\Framework\App\Request\Http))
#17 /var/www/preprod/vendor/magento/framework/Interception/Chain/Chain.php(70): Magento\Framework\App\FrontController\Interceptor->___callParent('dispatch', Array)
#18 /var/www/preprod/vendor/magento/framework/Interception/Interceptor.php(138): Magento\Framework\Interception\Chain\Chain->invokeNext('Magento\\Framewo...', 'dispatch', Object(Magento\Framework\App\FrontController\Interceptor), Array, 'install')
#19 /var/www/preprod/vendor/magento/framework/Module/Plugin/DbStatusValidator.php(69): Magento\Framework\App\FrontController\Interceptor->Magento\Framework\Interception\{closure}(Object(Magento\Framework\App\Request\Http))
#20 /var/www/preprod/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))
#21 /var/www/preprod/var/generation/Magento/Framework/App/FrontController/Interceptor.php(26): Magento\Framework\App\FrontController\Interceptor->___callPlugins('dispatch', Array, Array)
#22 /var/www/preprod/vendor/magento/framework/App/Http.php(135): Magento\Framework\App\FrontController\Interceptor->dispatch(Object(Magento\Framework\App\Request\Http))
#23 /var/www/preprod/vendor/magento/framework/App/Bootstrap.php(258): Magento\Framework\App\Http->launch()
#24 /var/www/preprod/index.php(39): Magento\Framework\App\Bootstrap->run(Object(Magento\Framework\App\Http))
#25 {main}

Magento goes on the class : Magento\Catalog\Controller\Adminhtml\Product\Attribute\Validate In the method : checkUniqueOption

/**
     * @param DataObject $response
     * @param array|null $options
     */
    private function checkUniqueOption(DataObject $response, array $options = null)
    {
        if (is_array($options) && !$this->isUniqueAdminValues($options['value'], $options['delete'])) {
            $this->setMessageToResponse($response, [__('The value of Admin must be unique.')]);
            $response->setError(true);
        }
    }

But $options[‘value’] doesn’t exist. Why ? Because on the backend the form disable the inputs :

image

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 6
  • Comments: 26 (4 by maintainers)

Most upvoted comments

If it can help anyone, here is a SQL query to identify duplicates:

SELECT *
  FROM eav_attribute_option_value AS a
  INNER JOIN eav_attribute_option AS ao USING (option_id)
  INNER JOIN (
    SELECT b.store_id, b.value_id, b.value, b.option_id, bo.attribute_id
    FROM eav_attribute_option_value AS b
    INNER JOIN eav_attribute_option AS bo USING (option_id)
  ) AS b ON ao.attribute_id = b.attribute_id
WHERE
  a.value_id != b.value_id
  AND a.store_id = b.store_id
  AND a.value = b.value

This issue is with Magento2.1.3. I am also facing this when trying to add a new option value to ‘color’ attribute and saving. Error is ‘The value of Admin must be unique.’ (I am sure what i am inserting is unique)

I had the same issue with 2.1.4 but could not find the cause.

The ugly workaround for me was to modify core temporarily:

diff -r ff0ac299b1dc www/vendor/magento/module-catalog/Controller/Adminhtml/Product/Attribute/Validate.php
--- a/www/vendor/magento/module-catalog/Controller/Adminhtml/Product/Attribute/Validate.php    Tue Mar 07 23:25:16 2017 +0100
+++ b/www/vendor/magento/module-catalog/Controller/Adminhtml/Product/Attribute/Validate.php    Wed Mar 08 12:30:27 2017 +0100
@@ -152,7 +152,7 @@
      */
     private function checkUniqueOption(DataObject $response, array $options = null)
     {
-        if (is_array($options) && !$this->isUniqueAdminValues($options['value'], $options['delete'])) {
+        if (is_array($options) && !$this->isUniqueAdminValues(@(array)$options['value'], $options['delete'])) {
             $this->setMessageToResponse($response, [__('The value of Admin must be unique.')]);
             $response->setError(true);
         }

@maximehuran, thank you for your report. We were not able to reproduce this issue by following the steps you provided. If you’d like to update it, please reopen the issue. We tested the issue on 2.3.0, 2.2.0, 2.1.9

I had the same problem with one of the Product Attributes. To fix the problem I run the query:

SELECT * FROM `mgbe_eav_attribute_option_value` where option_id in (SELECT option_id FROM `mgbe_eav_attribute_option` where attribute_id=81) ORDER BY `mgbe_eav_attribute_option_value`.`value` ASC

(you need to replace 81 with proper id - you can get it from the url from admin panel catalog/product_attribute/edit/attribute_id/81/key/…) and then just looked at the result and removed duplicates. I also had to remove corresponding values from mgbe_eav_attribute_option (based on option_id field) After removing all duplicates I was able to save Options

@maximehuran I’ve also this error in 2.1.7 version, it’s caused because (as you pointed above) the value input is disabled, but the “delete” hidden input is not disabled. We’ve fixed it disabling it when necessary (as M2 does by default for the other inputs): (This code is for Magento_Catalog module)

Index: view/adminhtml/templates/catalog/product/attribute/options.phtml
<+>UTF-8
===================================================================
--- view/adminhtml/templates/catalog/product/attribute/options.phtml
+++ view/adminhtml/templates/catalog/product/attribute/options.phtml
@@ -98,7 +98,11 @@
             </td>
             <?php endforeach; ?>
             <td id="delete_button_container_<%- data.id %>" class="col-delete">
-                <input type="hidden" class="delete-flag" name="option[delete][<%- data.id %>]" value="" />
+                <input type="hidden" class="delete-flag" name="option[delete][<%- data.id %>]" value=""
+                    <?php if ($block->getReadOnly() || $block->canManageOptionDefaultOnly()): ?>
+                        disabled="disabled"
+                    <?php endif; ?>
+                />
                 <?php if (!$block->getReadOnly() && !$block->canManageOptionDefaultOnly()):?>
                     <button
                         id="delete_button_<%- data.id %>"