magento2: AbstractAddress setData('custom_attributes', AttributeValue[]) breaks customAttributes

Preconditions (*)

  1. Magento 2.4.1

Steps to reproduce (*)

  1. Add custom attribute on customer address
  2. Call $address->setCustomAttributes('custom_attributes', $attributes) where $attributes is Magento\Framework\Api\AttributeValue Note that this is done several times in the checkout process if the custom attribute is added on the payload(i.e is present in the form). For example in \Magento\Quote\Model\ShippingMethodManagement::estimateByExtendedAddress()

Expected result (*)

  1. Custom attributes are added on the entity with their initial values

Actual result (*)

  1. The value of the custom attributes also contains the attribute code. This can be easily be debugged starting from AbstractAddress::setData() AbstractExtensibleModel::setData() and finally AbstractExtensibleModel::filterCustomAttributes() to this lines
foreach ($data[self::CUSTOM_ATTRIBUTES] as $code => $value) {
            if (!($value instanceof \Magento\Framework\Api\AttributeInterface)) {
                $data[self::CUSTOM_ATTRIBUTES][$code] = $this->customAttributeFactory->create()
                    ->setAttributeCode($code)
                    ->setValue($value);
            }
        }

where $value is an array that contains both the code and the value of the attribute because of this line in AbstractAddress::setData() $attribute = is_array($attribute) ? $attribute : $attribute->__toArray();

I don’t know what to say about the severity. This is pretty severe in my book, but the levels only seem to take into account a clean Magento install which I bet there isn’t a single one in production.


Please provide Severity assessment for the Issue as Reporter. This information will help during Confirmation and Issue triage processes.

  • Severity: S0 - Affects critical data or functionality and leaves users without workaround.
  • Severity: S1 - Affects critical data or functionality and forces users to employ a workaround.
  • Severity: S2 - Affects non-critical data or functionality and forces users to employ a workaround.
  • Severity: S3 - Affects non-critical data or functionality and does not force users to employ a workaround.
  • Severity: S4 - Affects aesthetics, professional look and feel, “quality” or “usability”.

About this issue

  • Original URL
  • State: open
  • Created 3 years ago
  • Reactions: 5
  • Comments: 29 (7 by maintainers)

Most upvoted comments

Found this bug today, upgrading to 2.4.2 an existing website that has custom attributes for customer address.

Since i’m not using multiline custom attributes i simply made a patch to remove the changes from commit https://github.com/magento/magento2/commit/91d61bdc5e5b85dcc5b51f7b539055e187a16790, if someone needs it:

Index: vendor/magento/module-customer/Model/Address/AbstractAddress.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/vendor/magento/module-customer/Model/Address/AbstractAddress.php b/vendor/magento/module-customer/Model/Address/AbstractAddress.php
--- a/vendor/magento/module-customer/Model/Address/AbstractAddress.php	(date 1615480763891)
+++ b/vendor/magento/module-customer/Model/Address/AbstractAddress.php	(date 1615480763891)
@@ -281,11 +281,6 @@
             $key = $this->_implodeArrayField($key);
         } elseif (is_array($value) && $this->isAddressMultilineAttribute($key)) {
             $value = $this->_implodeArrayValues($value);
-        } elseif (self::CUSTOM_ATTRIBUTES === $key && is_array($value)) {
-            foreach ($value as &$attribute) {
-                $attribute = is_array($attribute) ? $attribute : $attribute->__toArray();
-                $attribute = $this->processCustomAttribute($attribute);
-            }
         }
 
         return parent::setData($key, $value);

It looks like everything started with this commit https://github.com/magento/magento2/commit/91d61bdc5e5b85dcc5b51f7b539055e187a16790 which was meant to allow the multiline custom attributes to be saved