magento / magento2

Prior to making any Submission(s), you must sign an Adobe Contributor License Agreement, available here at: https://opensource.adobe.com/cla.html. All Submissions you make to Adobe Inc. and its affiliates, assigns and subsidiaries (collectively “Adobe”) are subject to the terms of the Adobe Contributor License Agreement.
http://www.magento.com
Open Software License 3.0
11.5k stars 9.31k forks source link

Array to String conversion error on checkout page when changin country - how to debug #12612

Closed fwolfst closed 5 years ago

fwolfst commented 6 years ago

Preconditions

  1. Magento 2.2.1
  2. php and mysql updated from ubuntu 16.04 repositories

Steps to reproduce

  1. I guess it is difficult to reproduce and configuration dependent. I'd be happy for hints how to debug this. The payment methods are set available for all allowed countries. There are shipping tablerates for the respictive countries too.
  2. Add one or more product(s) to cart
  3. Go to (onepage) checkout page
  4. Change the country

Expected result

  1. Shipping method and tax values and payment providers should change according to country selection.

Actual result

  1. Sometimes client sees a short red error message above the checkout page about Array to string conversion. In that case following is seen in var/log/exception.log: [2017-12-08 03:48:23] main.CRITICAL: Report ID: webapi-5a2a0b8746dca; Message: Notice: Array to string conversion in /var/www/XXX/vendor/magento/framework/DB/Adapter/Pdo/Mysql.php on line 2999 {"exception":"[object] (Exception(code: 0): Report ID: webapi-5a2a0b8746dca; Message: Notice: Array to string conversion in /var/www/XXX/vendor/magento/framework/DB/Adapter/Pdo/Mysql.php on line 2999 at /var/www/XXX/vendor/magento/framework/Webapi/ErrorProcessor.php:205, Exception(code: 0): Notice: Array to string conversion in /var/www/XXX/vendor/magento/framework/DB/Adapter/Pdo/Mysql.php on line 2999 at /var/www/XXX/vendor/magento/framework/App/ErrorHandler.php:61)"} [] The corresponding (shipping, tax, payment) values do not always change. Sometimes the error is not shown in frontend, then the log message differs slightly. In between configuration changes or separete tests I flush caches and clear the browser session (FF, Ctrl+F5).

[2017-12-07 23:57:04] main.CRITICAL: Notice: Array to string conversion in /var/www/XXX/vendor/magento/framework/DB/Adapter/Pdo/Mysql.php on line 2999 {"exception":"[object] (Exception(code: 0): Notice: Array to string conversion in /var/www/XXX/vendor/magento/framework/DB/Adapter/Pdo/Mysql.php on line 2999 at /var/www/XXX/vendor/magento/framework/App/ErrorHandler.php:61)"} [] I am sorry not to be able to be more precise here but any help on getting a more detailed stacktrace or more information on where the error actually comes from would be greatly appreciated. I hacked the corresponding Mysql.php file and printed the "array" contents into a file. It showed up an empty list ("()" afair).

RishabhRkRai commented 6 years ago

I also have the same error message for the logged in users.

magento-engcom-team commented 6 years ago

@fwolfst , thank you for your report. We were not able to reproduce this issue by following the steps you provided. Please provide more detailed steps to reproduce or try to reproduce this issue on a clean installation.

fwolfst commented 6 years ago

@magento-engcom-team I guess its a difficult task to pinpoint it down. Of course this might have to do with extensions, configuration or migrated data. But I am happy if somebody shares a few tipps on how to debug this further (stacktrace etc).

magento-engcom-team commented 6 years ago

@fwolfst , thank for you update. please refer to the Community Forums or the Magento Stack Exchange site for advice or general discussion about this issue. The GitHub issue tracker is intended for Magento Core technical issues only.

patchee500 commented 6 years ago

I also ran into this issue. From what I am seeing this happens only to users who get their customer group emulated (and vat number validated) during checkout. (customers with a valid tax id shipping to another country within the EU that is)

When Magento fetches an address object from db it seems to turn the region data into an array (Magento\Customer\Model\Address\AbstractAddress::getDataModel, Line 533).

If later on vat validation is performed (Magento\Quote\Observer\Frontend\Quote\Address\VatValidator, Line 43) there is a (\Magento\Quote\Model\Quote\Address) Model being saved that still has the region split as array.

As the data is getting persisted into quote_address where region is a varchar obviously Magento is trying to convert the array into a string which produces the error.

This does not look like an error caused by extensions or migrated data.

hostep commented 6 years ago

We also run into this problem on a Magento 2.1.11 installation. The analysis of @patchee500 seems to be correct, it seems to be triggered by the vat validation.

If someone is interested in the full stacktrace:

[2018-02-07 21:54:13] main.CRITICAL: Exception: Notice: Array to string conversion in vendor/magento/framework/DB/Adapter/Pdo/Mysql.php on line 2929 in vendor/magento/framework/App/ErrorHandler.php:61
Stack trace:
#0 vendor/magento/framework/DB/Adapter/Pdo/Mysql.php(2929): Magento\Framework\App\ErrorHandler->handler(8, 'Array to string...', '...', 2929, Array)
#1 vendor/magento/framework/Model/ResourceModel/AbstractResource.php(168): Magento\Framework\DB\Adapter\Pdo\Mysql->prepareColumnValue(Array, Array)
#2 vendor/magento/framework/Model/ResourceModel/Db/AbstractDb.php(728): Magento\Framework\Model\ResourceModel\AbstractResource->_prepareDataForTable(Object(Magento\Quote\Model\Quote\Address), 'quote_address')
#3 vendor/magento/framework/Model/ResourceModel/Db/AbstractDb.php(784): Magento\Framework\Model\ResourceModel\Db\AbstractDb->prepareDataForUpdate(Object(Magento\Quote\Model\Quote\Address))
#4 vendor/magento/framework/Model/ResourceModel/Db/AbstractDb.php(403): Magento\Framework\Model\ResourceModel\Db\AbstractDb->updateObject(Object(Magento\Quote\Model\Quote\Address))
#5 vendor/magento/framework/Model/AbstractModel.php(636): Magento\Framework\Model\ResourceModel\Db\AbstractDb->save(Object(Magento\Quote\Model\Quote\Address))
#6 vendor/magento/module-quote/Observer/Frontend/Quote/Address/VatValidator.php(73): Magento\Framework\Model\AbstractModel->save()
#7 vendor/magento/module-quote/Observer/Frontend/Quote/Address/CollectTotalsObserver.php(96): Magento\Quote\Observer\Frontend\Quote\Address\VatValidator->validate(Object(Magento\Quote\Model\Quote\Address), '1')
#8 vendor/magento/framework/Event/Invoker/InvokerDefault.php(73): Magento\Quote\Observer\Frontend\Quote\Address\CollectTotalsObserver->execute(Object(Magento\Framework\Event\Observer))
#9 vendor/magento/framework/Event/Invoker/InvokerDefault.php(61): Magento\Framework\Event\Invoker\InvokerDefault->_callObserverMethod(Object(Magento\Quote\Observer\Frontend\Quote\Address\CollectTotalsObserver), Object(Magento\Framework\Event\Observer))
#10 vendor/magento/framework/Event/Manager.php(66): Magento\Framework\Event\Invoker\InvokerDefault->dispatch(Array, Object(Magento\Framework\Event\Observer))
#11 var/generation/Magento/Framework/Event/Manager/Proxy.php(95): Magento\Framework\Event\Manager->dispatch('sales_quote_add...', Array)
#12 vendor/magento/module-quote/Model/Quote/TotalsCollector.php(259): Magento\Framework\Event\Manager\Proxy->dispatch('sales_quote_add...', Array)
#13 vendor/magento/module-quote/Model/ShippingMethodManagement.php(295): Magento\Quote\Model\Quote\TotalsCollector->collectAddressTotals(Object(Magento\Quote\Model\Quote), Object(Magento\Quote\Model\Quote\Address))
#14 vendor/magento/module-quote/Model/ShippingMethodManagement.php(248): Magento\Quote\Model\ShippingMethodManagement->getShippingMethods(Object(Magento\Quote\Model\Quote), Object(Magento\Customer\Model\Data\Address))
#15 [internal function]: Magento\Quote\Model\ShippingMethodManagement->estimateByAddressId(276, 862)
#16 vendor/magento/module-webapi/Controller/Rest.php(307): call_user_func_array(Array, Array)
#17 vendor/magento/module-webapi/Controller/Rest.php(216): Magento\Webapi\Controller\Rest->processApiRequest()
#18 var/generation/Magento/Webapi/Controller/Rest/Interceptor.php(24): Magento\Webapi\Controller\Rest->dispatch(Object(Magento\Framework\App\Request\Http))
#19 vendor/magento/framework/App/Http.php(135): Magento\Webapi\Controller\Rest\Interceptor->dispatch(Object(Magento\Framework\App\Request\Http))
#20 vendor/magento/framework/App/Bootstrap.php(258): Magento\Framework\App\Http->launch()
#21 pub/index.php(37): Magento\Framework\App\Bootstrap->run(Object(Magento\Framework\App\Http))
#22

{main}

@patchee500: have you already found a fix for this problem?

@magento-engcom-team: somehow I have the power to reopen this ticket, so I'm doing so since I believe this is a core bug. Although there aren't any good steps provided yet to reproduce this issue. If I'm in error, feel free to close again.

And this is a duplicate of https://github.com/magento/magento2/issues/11654 btw, but this issue seems to have more interesting information.

hostep commented 6 years ago

Here are the exact steps to reproduce, I tested it multiple times to make sure I didn't make any mistakes

Preconditions

  1. Clean Magento instance, code from 2.1-develop branch, current commit: c1b771005bd
  2. PHP 7.0.27

Steps to reproduce

  1. Go to the backend of Magento
  2. Create a category and product, so you have something to put in the cart
  3. Go to Stores => Configuration => Customers => Customer Configuration => Create New Account Options
  4. Change these settings:
    • Enable Automatic Assignment to Customer Group => Yes
    • Tax Calculation Based On => Shipping Address
    • Validate on Each Transaction => Yes
    • Show VAT Number on Storefront => Yes
    • The rest can stay as is, defaults are fine
  5. Flush the cache
  6. In the frontend, create a new account
  7. Then while you are logged in, in the my account section, go to Address Book and add a new address with a VAT Number (doesn't have to be valid, just use '0123' or something), pick Belgium as country (any EU country should work, but I tested with Belgium)
  8. Create yet another address, use a different name, but the same address (again Belgium) and the same VAT Number, check 'Use as my default billing address'
  9. Verify that you now have a default shipping and default billing address which have the same address, but only differ in their name
  10. Add the test product to your cart
  11. Go to the checkout

Expected result

  1. Should see no error and a shipping method available to pick from

Actual result

  1. Getting the error:
    Notice: Array to string conversion in lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php on line 2929
  2. Seeing no shipping methods to pick from

Fix which hasn't been tested very well

I wrote a small module with a preference for the Magento\Quote\Observer\Frontend\Quote\Address\VatValidator and copied the validate method and added some extra lines of code:

@@ -63,6 +34,20 @@
                 $merchantVatNumber
             );

+            if (is_array($quoteAddress->getRegion()))
+            {
+                $regionData = $quoteAddress->getRegion();
+                if (array_key_exists('region_code', $regionData))
+                {
+                    $quoteAddress->setRegionCode($regionData['region_code']);
+                }
+                if (array_key_exists('region_id', $regionData))
+                {
+                    $quoteAddress->setRegionId($regionData['region_id']);
+                }
+                $quoteAddress->setRegion(null);
+            }
+
             // Store validation results in corresponding quote address
             $quoteAddress->setVatIsValid((int)$validationResult->getIsValid());
             $quoteAddress->setVatRequestId($validationResult->getRequestIdentifier());

This is most likely not the correct solution, but it seems to work...

@magento-engcom-team: can you double check and verify and then add the G3 Passed label once verified? Thanks!

patchee500 commented 6 years ago

@hostep Since the region data was of no importance in our case, we fixed this by simply unsetting the region data before vat validation was performed in a Plugin.
(We also targeted the Magento\Quote\Observer\Frontend\Quote\Address\VatValidator::validate Method)

I'm also unsure if this method is the correct place to add the region splitting, this is something @magento-engcom-team needs to decide. Hopefully they now acknowledge the existence of this issue.

magento-engcom-team commented 6 years ago

@hostep , thank for you update with detal steps to reproduce. We've acknowledged the issue and added to our backlog

hostep commented 6 years ago

@magento-engcom-team: why did you add the tags Fixed in 2.2.x and Fixed in 2.3.x? Did you actually test this?

Because I just tested this to be certain:

Can you remove those two labels and add the Reproduced on 2.2.x and Reproduced on 2.3.x labels please?

Thanks!

magento-engcom-team commented 6 years ago

@hostep , sorry for mistake, we rechecked this issue and added all correct labeles

farhadfrz commented 6 years ago

Any progress on this issue? We get both of the following error messages simultaneously (using Magento 2.1.12):

fratob85 commented 6 years ago

I checked the problem. Error messages are displayed because some invalid data is saved in the input validation phase.

See \Magento\Quote\Observer\Frontend\Quote\Address\VatValidator::validate

$quoteAddress->setVatRequestSuccess($validationResult->getRequestSuccess());
$quoteAddress->setValidatedVatNumber($customerVatNumber);
$quoteAddress->setValidatedCountryCode($customerCountryCode);
$quoteAddress->save();

When saving, the region data item contains an array with region_code and some additional values. This usually happens when you do not have a region database for the selected country.

P.S: Is the save action really necessary here?

jakoblundsted commented 6 years ago

The solution from @hostep worked for me.

SannePetersNL commented 6 years ago

Also had this problem in 2.2.5, @hostep's solution worked for me to.

UrbanSurfers commented 6 years ago

same here in 2.1.9 and Braintree Gateway, @hostep is there a way you share your full module or describe steps to create my own ? sorry for being to noob but this kind of tweak goes well beyond my skills... according @jakoblundsted and @SannePetersNL your solution seems to work maybe they can help me also ?? Once again thanks in advance for your time.

hostep commented 6 years ago

@UrbanSurfers : sorry, at the moment I can't remember and can't find the project where we've fixed this. As for how to create a preference in a custom module in Magento 2, you can probably search for some tutorials: https://www.google.com/search?q=magento2+tutorial+preferences, but if you've never created a custom module before, it might be a bit complex...

Or maybe one of the other people in here can help you further.

tuyennn commented 5 years ago

Well my scenario, seem like the shipping Address and Billing Address has street was an array. To fix this temporary implode the street with \n then set it back to address.

Here is the patch for 2.1.9


From d9ef070e6b5cd2da89d87ae121c1e7edd2892f29 Mon Sep 17 00:00:00 2001
From: tuyennn <thinghost76@gmail.com>
Date: Fri, 7 Dec 2018 18:47:03 +0700
Subject: [PATCH] Issue #12612 Array to String conversion error on checkout
 page

---
 .../Model/ShippingInformationManagement.php               | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/vendor/magento/module-checkout/Model/ShippingInformationManagement.php b/vendor/magento/module-checkout/Model/ShippingInformationManagement.php
index 5f972bf9..bf662bed 100644
--- a/vendor/magento/module-checkout/Model/ShippingInformationManagement.php
+++ b/vendor/magento/module-checkout/Model/ShippingInformationManagement.php
@@ -142,6 +142,14 @@ class ShippingInformationManagement implements \Magento\Checkout\Api\ShippingInf
             throw new StateException(__('Shipping address is not set'));
         }

+        if (is_array($s = $address->getData('street'))) {
+            $address->setData('street', implode("\n", $s));
+        }
+
+        if (is_array($s = $billingAddress->getData('street'))) {
+            $billingAddress->setData('street', implode("\n", $s));
+        }
+
         /** @var \Magento\Quote\Model\Quote $quote */
         $quote = $this->quoteRepository->getActive($cartId);
         $quote = $this->prepareShippingAssignment($quote, $address, $carrierCode . '_' . $methodCode);
-- 
2.19.2
matin73 commented 5 years ago

Same issue in 2.2.x (latest version). @hostep's solution worked for me to.

magento-engcom-team commented 5 years ago

Hi @fwolfst. Thank you for your report. The issue has been fixed in magento/magento2#22558 by @Leone in 2.3-develop branch Related commit(s):

The fix will be available with the upcoming 2.3.3 release.

adarshkhatri commented 4 years ago

In my 2.3.3-p1 I have a couple of incidents where customers were charged but Magento was not able to create order.

In the log I see this:

Saving order 1000023605 failed: Notice: Array to string conversion in /vendor/magento/framework/DB/Adapter/Pdo/Mysql.php

I can change the country just fine.

My biggest problem is that I cannot reproduce this. Can anyone guide me in here?

Customer explained that after hitting the place order button, the checkout page froze but then PayPal sent them a successful payment email.