4

When I add a product to the cart, it shows the error "Invalid address id". How can I solve this issue?

7
  • 1
    check using clera broswer cache and cache flush Commented Oct 6, 2017 at 5:16
  • Done. But no changes. Still shows that error.
    – Rita Jose
    Commented Oct 6, 2017 at 6:12
  • are you login in website, right? Commented Oct 6, 2017 at 6:13
  • @DhirenVasoya yes, after login & add a product to cart
    – Rita Jose
    Commented Oct 6, 2017 at 6:16
  • The issue is that, dua to some reason the address which is store for customer is mismatch. do you have database access? Commented Oct 6, 2017 at 6:21

4 Answers 4

4

This may be due to having multiple active quotes for a logged-in customer.

Note: Multiple Quote creation may happen in different kinds of scenarios and my case happened due to custom extension/module.

Solution/Cross-Check:

Login to your database and run following queries,

select entity_id, is_active from quote where customer_id = <customer_id>;

If you found is_active for more than one quote, please run the following query to de-activate all quotes.

delete from quote where customer_id = <customer_id> and is_active = 1;

Note: Please make sure <customer_id>, replace with the actual customer id, which can get from Admin -> Customer.

1
  • It's working for me, Thanks Commented Mar 24, 2023 at 7:25
3

This is a core Magento2 issue. I have created a module for this solution.

Steps to reproduce the issue.

1.Login

  1. Add a product to your basket (remember which product you added)

  2. Go to checkout and select a delivery address (do not process a transaction)

  3. Remove the product from the cart

  4. Delete the address you selected from your account

  5. Add the same product as before to your basket

Then an error pops up saying "Invalid address id".

This is related to a missing address id in quote_address database table. The reference to address which is removed from customer address book still exists in this table. Magento tries to fetch the customer address in address repository using customer id and errors.

This module only helps to avoid the issue in future. For the existing issue, we have to edit the database entry itself.

for eg: if the error shows like "invalid address id 185". check the address id with 185 in quote_address table. Then replace the corresponding customer_id against that address_id as "NULL". The issue should be resolved and you should once again be able to add a product to the cart. Module creation steps.

in Custom/DefaultAddress/registration.php

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Custom_DefaultAddress',
 __DIR__
);
?>

in Custom/DefaultAddress/etc/module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Custom_DefaultAddress" setup_version="0.0.1"/>
</config>

in Custom/DefaultAddress/etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
  <preference for="Magento\Customer\Controller\Address\Delete" type="Custom\DefaultAddress\Controller\Rewrite\Address\Delete" />
<preference for="Magento\Customer\Controller\Adminhtml\Index\Save" type="Custom\DefaultAddress\Controller\Adminhtml\Rewrite\Index\Save" />

in Custom/DefaultAddress/etc/frontend/routes.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd">
 <router id="standard">
<route id="dafaultaddress" frontName="dafaultaddress">
<module name="Custom_DefaultAddress" />
</route>
</router>
</config>

in Custom/DefaultAddress/Controller/Adminhtml/Rewrite/Index/Save.php

<?php
namespace Custom\DefaultAddress\Controller\Adminhtml\Rewrite\Index;
use Magento\Customer\Api\AddressMetadataInterface;
use Magento\Customer\Api\CustomerMetadataInterface;
use Magento\Customer\Api\Data\CustomerInterface;
use Magento\Customer\Controller\RegistryConstants;
use Magento\Customer\Model\EmailNotificationInterface;
use Magento\Customer\Model\Metadata\Form;
use Magento\Framework\Exception\LocalizedException;

class Save extends \Magento\Customer\Controller\Adminhtml\Index\Save
{
  private $emailNotification;

/**
 * Reformat customer account data to be compatible with customer service interface
 *
 * @return array
 */
protected function _extractCustomerData()
{
    $customerData = [];
    if ($this->getRequest()->getPost('customer')) {
        $additionalAttributes = [
            CustomerInterface::DEFAULT_BILLING,
            CustomerInterface::DEFAULT_SHIPPING,
            'confirmation',
            'sendemail_store_id',
            'extension_attributes',
        ];

        $customerData = $this->_extractData(
            $this->getRequest(),
            'adminhtml_customer',
            CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER,
            $additionalAttributes,
            'customer'
        );
    }

    if (isset($customerData['disable_auto_group_change'])) {
        $customerData['disable_auto_group_change'] = (int) filter_var(
            $customerData['disable_auto_group_change'],
            FILTER_VALIDATE_BOOLEAN
        );
    }

    return $customerData;
}

/**
 * Perform customer data filtration based on form code and form object
 *
 * @param \Magento\Framework\App\RequestInterface $request
 * @param string $formCode The code of EAV form to take the list of attributes from
 * @param string $entityType entity type for the form
 * @param string[] $additionalAttributes The list of attribute codes to skip filtration for
 * @param string $scope scope of the request
 * @param \Magento\Customer\Model\Metadata\Form $metadataForm to use for extraction
 * @return array Filtered customer data
 * @SuppressWarnings(PHPMD.NPathComplexity)
 */
protected function _extractData(
    \Magento\Framework\App\RequestInterface $request,
    $formCode,
    $entityType,
    $additionalAttributes = [],
    $scope = null,
    \Magento\Customer\Model\Metadata\Form $metadataForm = null
) {
    $metadataForm = $metadataForm ? $metadataForm : $this->getMetadataForm($entityType, $formCode, $scope);
    $formData = $metadataForm->extractData($request, $scope);

    // Initialize additional attributes
    /** @var \Magento\Framework\DataObject $object */
    $object = $this->_objectFactory->create(['data' => $request->getPostValue()]);
    $requestData = $object->getData($scope);
    foreach ($additionalAttributes as $attributeCode) {
        $formData[$attributeCode] = isset($requestData[$attributeCode]) ? $requestData[$attributeCode] : false;
    }

    $result = $metadataForm->compactData($formData);

    // Re-initialize additional attributes
    $formData = array_replace($formData, $result);

    // Unset unused attributes
    $formAttributes = $metadataForm->getAttributes();
    foreach ($formAttributes as $attribute) {
        /** @var \Magento\Customer\Api\Data\AttributeMetadataInterface $attribute */
        $attributeCode = $attribute->getAttributeCode();
        if ($attribute->getFrontendInput() != 'boolean'
            && $formData[$attributeCode] === false
        ) {
            unset($formData[$attributeCode]);
        }
    }

    if (empty($formData['extension_attributes'])) {
        unset($formData['extension_attributes']);
    }

    return $formData;
}

/**
 * Saves default_billing and default_shipping flags for customer address
 *
 * @param array $addressIdList
 * @param array $extractedCustomerData
 * @return array
 */
protected function saveDefaultFlags(array $addressIdList, array & $extractedCustomerData)
{
    $result = [];
    $extractedCustomerData[CustomerInterface::DEFAULT_BILLING] = null;
    $extractedCustomerData[CustomerInterface::DEFAULT_SHIPPING] = null;
    foreach ($addressIdList as $addressId) {
        $scope = sprintf('address/%s', $addressId);
        $addressData = $this->_extractData(
            $this->getRequest(),
            'adminhtml_customer_address',
            AddressMetadataInterface::ENTITY_TYPE_ADDRESS,
            ['default_billing', 'default_shipping'],
            $scope
        );

        if (is_numeric($addressId)) {
            $addressData['id'] = $addressId;
        }
        // Set default billing and shipping flags to customer
        if (!empty($addressData['default_billing']) && $addressData['default_billing'] === 'true') {
            $extractedCustomerData[CustomerInterface::DEFAULT_BILLING] = $addressId;
            $addressData['default_billing'] = true;
        } else {
            $addressData['default_billing'] = false;
        }
        if (!empty($addressData['default_shipping']) && $addressData['default_shipping'] === 'true') {
            $extractedCustomerData[CustomerInterface::DEFAULT_SHIPPING] = $addressId;
            $addressData['default_shipping'] = true;
        } else {
            $addressData['default_shipping'] = false;
        }
        $result[] = $addressData;
    }
    return $result;
}

/**
 * Reformat customer addresses data to be compatible with customer service interface
 *
 * @param array $extractedCustomerData
 * @return array
 */
protected function _extractCustomerAddressData(array & $extractedCustomerData)
{
    $addresses = $this->getRequest()->getPost('address');
    $result = [];
    if (is_array($addresses)) {
        if (isset($addresses['_template_'])) {
            unset($addresses['_template_']);
        }

        $addressIdList = array_keys($addresses);
        $result = $this->saveDefaultFlags($addressIdList, $extractedCustomerData);
    }

    return $result;
}

/**
 * Save customer action
 *
 * @return \Magento\Backend\Model\View\Result\Redirect
 * @SuppressWarnings(PHPMD.CyclomaticComplexity)
 * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
 * @SuppressWarnings(PHPMD.NPathComplexity)
 */
public function execute()
{
    $returnToEdit = false;
    $originalRequestData = $this->getRequest()->getPostValue();

    $customerId = $this->getCurrentCustomerId();

    if ($originalRequestData) {
        try {
            // optional fields might be set in request for future processing by observers in other modules
            $customerData = $this->_extractCustomerData();
            $addressesData = $this->_extractCustomerAddressData($customerData);

            if ($customerId) {
                $currentCustomer = $this->_customerRepository->getById($customerId);
                $customerData = array_merge(
                    $this->customerMapper->toFlatArray($currentCustomer),
                    $customerData
                );
                $customerData['id'] = $customerId;
            }

            /** @var CustomerInterface $customer */
            $customer = $this->customerDataFactory->create();
            $this->dataObjectHelper->populateWithArray(
                $customer,
                $customerData,
                '\Magento\Customer\Api\Data\CustomerInterface'
            );
            $addresses = [];
            foreach ($addressesData as $addressData) {
                $region = isset($addressData['region']) ? $addressData['region'] : null;
                $regionId = isset($addressData['region_id']) ? $addressData['region_id'] : null;
                $addressData['region'] = [
                    'region' => $region,
                    'region_id' => $regionId,
                ];
                $addressDataObject = $this->addressDataFactory->create();
                $this->dataObjectHelper->populateWithArray(
                    $addressDataObject,
                    $addressData,
                    '\Magento\Customer\Api\Data\AddressInterface'
                );
                $addresses[] = $addressDataObject;
            }

            $this->_eventManager->dispatch(
                'adminhtml_customer_prepare_save',
                ['customer' => $customer, 'request' => $this->getRequest()]
            );
            $customer->setAddresses($addresses);
            if (isset($customerData['sendemail_store_id'])) {
                $customer->setStoreId($customerData['sendemail_store_id']);
            }

            // Save customer
            if ($customerId) {
                $this->_customerRepository->save($customer);
                $this->getEmailNotification()->credentialsChanged($customer, $currentCustomer->getEmail());
            } else {
                $customer = $this->customerAccountManagement->createAccount($customer);
                $customerId = $customer->getId();
            }
            $this->_resources = \Magento\Framework\App\ObjectManager::getInstance()->get('Magento\Framework\App\ResourceConnection');
            $connection= $this->_resources->getConnection();
            $customer_addressquote_table = $this->_resources->getTableName('quote_address');
            $sql_customeraddressquote = "SELECT customer_address_id FROM ".$customer_addressquote_table." WHERE customer_id = ".$customerId." ";
            $connection->query($sql_customeraddressquote);
            $result_customeraddress_id = $connection->fetchAll($sql_customeraddressquote);
            if(!empty($result_customeraddress_id)){
                foreach( $result_customeraddress_id as $result_customeraddress) {
                    foreach($result_customeraddress as $result_customeraddress_entity){
                        if($result_customeraddress_entity != ''){
                            $customeraddress_table = $this->_resources->getTableName('customer_address_entity');
                            $sql_customeraddress = "SELECT * FROM ".$customeraddress_table." WHERE entity_id = ".$result_customeraddress_entity." ";
                            $connection->query($sql_customeraddress);
                            $resultaddress = $connection->fetchAll($sql_customeraddress);
                            if(empty($resultaddress)){

                                $themeTable = $this->_resources->getTableName('quote_address');
                                $sql = "Update " . $themeTable . " Set customer_address_id = null where customer_address_id = ".$result_customeraddress_entity."";
                                $connection->query($sql);
                            }
                        }
                   }
                }
            }

            $isSubscribed = null;
            if ($this->_authorization->isAllowed(null)) {
                $isSubscribed = $this->getRequest()->getPost('subscription');
            }
            if ($isSubscribed !== null) {
                if ($isSubscribed !== 'false') {
                    $this->_subscriberFactory->create()->subscribeCustomerById($customerId);
                } else {
                    $this->_subscriberFactory->create()->unsubscribeCustomerById($customerId);
                }
            }

            // After save
            $this->_eventManager->dispatch(
                'adminhtml_customer_save_after',
                ['customer' => $customer, 'request' => $this->getRequest()]
            );
            $this->_getSession()->unsCustomerFormData();
            // Done Saving customer, finish save action
            $this->_coreRegistry->register(RegistryConstants::CURRENT_CUSTOMER_ID, $customerId);
            $this->messageManager->addSuccess(__('You saved the customer.'));
            $returnToEdit = (bool)$this->getRequest()->getParam('back', false);
        } catch (\Magento\Framework\Validator\Exception $exception) {
            $messages = $exception->getMessages();
            if (empty($messages)) {
                $messages = $exception->getMessage();
            }
            $this->_addSessionErrorMessages($messages);
            $this->_getSession()->setCustomerFormData($originalRequestData);
            $returnToEdit = true;
        } catch (LocalizedException $exception) {
            $this->_addSessionErrorMessages($exception->getMessage());
            $this->_getSession()->setCustomerFormData($originalRequestData);
            $returnToEdit = true;
        } catch (\Exception $exception) {
            $this->messageManager->addException($exception, __('Something went wrong while saving the customer.'));
            $this->_getSession()->setCustomerFormData($originalRequestData);
            $returnToEdit = true;
        }
    }
    $resultRedirect = $this->resultRedirectFactory->create();
    if ($returnToEdit) {
        if ($customerId) {
            $resultRedirect->setPath(
                'customer/*/edit',
                ['id' => $customerId, '_current' => true]
            );
        } else {
            $resultRedirect->setPath(
                'customer/*/new',
                ['_current' => true]
            );
        }
    } else {
        $resultRedirect->setPath('customer/index');
    }
    return $resultRedirect;
}

/**
 * Get email notification
 *
 * @return EmailNotificationInterface
 * @deprecated
 */
private function getEmailNotification()
{
    if (!($this->emailNotification instanceof EmailNotificationInterface)) {
        return \Magento\Framework\App\ObjectManager::getInstance()->get(
            EmailNotificationInterface::class
        );
    } else {
        return $this->emailNotification;
    }
}

/**
 * Get metadata form
 *
 * @param string $entityType
 * @param string $formCode
 * @param string $scope
 * @return Form
 */
private function getMetadataForm($entityType, $formCode, $scope)
{
    $attributeValues = [];

    if ($entityType == CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER) {
        $customerId = $this->getCurrentCustomerId();
        if ($customerId) {
            $customer = $this->_customerRepository->getById($customerId);
            $attributeValues = $this->customerMapper->toFlatArray($customer);
        }
    }

    if ($entityType == AddressMetadataInterface::ENTITY_TYPE_ADDRESS) {
        $scopeData = explode('/', $scope);
        if (isset($scopeData[1]) && is_numeric($scopeData[1])) {
            $customerAddress = $this->addressRepository->getById($scopeData[1]);
            $attributeValues = $this->addressMapper->toFlatArray($customerAddress);
        }
    }

    $metadataForm = $this->_formFactory->create(
        $entityType,
        $formCode,
        $attributeValues,
        false,
        Form::DONT_IGNORE_INVISIBLE
    );

    return $metadataForm;
}

/**
 * Retrieve current customer ID
 *
 * @return int
 */
private function getCurrentCustomerId()
{
    $originalRequestData = $this->getRequest()->getPostValue(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER);

    $customerId = isset($originalRequestData['entity_id'])
        ? $originalRequestData['entity_id']
        : null;

    return $customerId;
}
}

in Custom/DefaultAddress/Controller/Rewrite/Address/Delete.php

<?php
namespace Custom\DefaultAddress\Controller\Rewrite\Address;
class Delete extends \Magento\Customer\Controller\Address\Delete
{

    public function execute()
    {
        $addressId = $this->getRequest()->getParam('id', false);

        $address = $this->_addressRepository->getById($addressId);
        if ($addressId && $this->_formKeyValidator->validate($this->getRequest())) {
            try {
                $address = $this->_addressRepository->getById($addressId);
                if ($address->getCustomerId() === $this->_getSession()->getCustomerId()) {
                    $this->_addressRepository->deleteById($addressId);
                    $this->messageManager->addSuccess(__('You deleted the address.'));
                    $customer_id =   $address->getCustomerId();
                    $this->_resources = \Magento\Framework\App\ObjectManager::getInstance()->get('Magento\Framework\App\ResourceConnection');
                    $connection= $this->_resources->getConnection();

                    $customer_addressquote_table = $this->_resources->getTableName('quote_address');
                    $sql_customeraddressquote = "SELECT * FROM ".$customer_addressquote_table." WHERE customer_address_id = ".$addressId." ";
                    $connection->query($sql_customeraddressquote);
                    $result_customeraddress_id = $connection->fetchAll($sql_customeraddressquote);
                    if(!empty($result_customeraddress_id)){
                        $customer_address_table = $this->_resources->getTableName('quote_address');
                        $sql_customeraddress = "SELECT customer_address_id FROM ".$customer_address_table." WHERE customer_address_id = ".$addressId." ";

                        $connection->query($sql_customeraddress);
                        $result_customeraddress_id = $connection->fetchAll($sql_customeraddress);

                        foreach( $result_customeraddress_id as $result_customeraddress) {
                            foreach($result_customeraddress as $result_customeraddress_entity){
                                $themeTable = $this->_resources->getTableName('quote_address');
                                $sql = "Update " . $themeTable . " Set customer_address_id = null where customer_address_id = ".$result_customeraddress_entity."";
                                $connection->query($sql);
                           }

                        }
                    }
                } else {
                    $this->messageManager->addError(__('We can\'t delete the address right now.'));
                }
            } catch (\Exception $other) {
                $this->messageManager->addException($other, __('We can\'t delete the address right now.'));
            }
        }
        return $this->resultRedirectFactory->create()->setPath('*/*/index');
    }
}
4
  • Great! I was facing the issue and I resolved it using your solution! thank you, you saved my time! Commented May 14, 2018 at 11:13
  • Hi, I still got the error after using this solution.
    – Rajan Soni
    Commented May 30, 2018 at 11:05
  • @RajanSoni Why don't you try this one? github.com/vinaysikarwar/AddressIssue Commented Jul 17, 2019 at 13:06
  • Using Magento 2.2 and it was under the column "customer_address_id" for the ID found in the column instead of "address_id".
    – KyleBunga
    Commented Jan 29, 2021 at 20:28
1

When I Use this extension, I get the below error.

Exception #0 (Exception): Warning: Declaration of Custom\DefaultAddress\Controller\Adminhtml\Rewrite\Index\Save::_extractData(Magento\Framework\App\RequestInterface $request, $formCode, $entityType,

0
0

Seems to be a known issue: https://github.com/magento/magento2/issues/7570

Don't run this in production, but a quick fix if you just need it working locally is to run the following SQL:

DELETE FROM quote_address;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.