1

So I'm on Commerce -> Configuration -> Orders -> Checkout flows. I'm editing a flow (it's the same with any of them), so i.e. I'm at page:

/admin/commerce/config/checkout-flows/manage/shipping

and for some items (i.e. "Login or continue as guest", "Contact information"...) with the option I also have gear icon on right for opening some settings block.

Until recently that worked well, but now, when I click gear icon spinner appears for short time and nothing happens.

In error log I see message:

LogicException: The database connection is not serializable. This probably means you are serializing an object that has an indirect reference to the database connection. Adjust your code so that is not necessary. Alternatively, look at DependencySerializationTrait as a temporary solution. in Drupal\Core\Database\Connection->__sleep() (line 1573 of /var/www/html/drupal/web/core/lib/Drupal/Core/Database/Connection.php).

From browser network tab I can see that url:

http://sitename.test/admin/commerce/config/checkout-flows/manage/shipping?destination=/admin/commerce/config/checkout-flows&ajax_form=1&_wrapper_format=drupal_ajax

is called and response was:

500 Service unavailable (with message)

Any idea what could cause this error and how to solve it?

4

I experienced the same problem. It's not a commerce issue, and there is no general rule which module causes the problem.

The problem probably occurs, because one of your checkout panes depend on a service, which has an indirect dependency to Drupals database connection -- Drupals database connection is not serializable and this causes the error.

It's not that easy to debug, because the form is soooo big, and loads all the CheckoutPane Plugin Forms. The good news: I figured out a way to debug the issue:

First of all, we need to determine the problematic checkout pane. To do that, we loop over all panes and try to serialize them independently. Temporary add the following snippet to the Drupal\Core\Form\FormState::getCacheableArray()

if(!empty($this->getStorage()['panes'])) {
  // loop over all panes and try to serialize each independently, 
  // catch possible serialization errors and dump the problematic pane.
  foreach($this->getStorage()['panes'] as $key => $pane) {
    try {
      serialize($pane);
    } catch(\Throwable $throwable) {
      // dump pane, which causes the error and die
      dd($pane);
    }
  }
}

FYI: The dd() output does not look very pretty in chrome's network tab (all the properties are expanded). I copied the request as CURL Request (in chrome: right click on the XHR Request --> copy as CURL) and pasted it into Insomnia (my Rest Client). When executing the Request there, the dd() is displayed as usual with the possibility to expand and collapse the properties. That makes it much easier to find the problematic service..

There should be a dumped object, which is the non-serializable checkout pane. If thats not the case, you have a completely different problem than me and you can skip this answer. But if there is a dump of the pane, you can now have a detailed look at the properties of the pane. It is necessary, that the properties which are services have a _serviceId property; if this property is missing, the Pane's DependencySerializationTrait isn't recognizing the Service as a Service.

Unfortunately, there can be Services, which haven't the _serviceId property. In my case, a contrib module (mail_login) provided a decoration service, which decorated the service user.auth. The service user.auth is injected as dependency to the Login-pane (and I think another one too). This decorated service, had no _serviceId property, so Drupal tried to serialize the the user.auth Service. The problem is now, that the user.auth service has a dependency to Drupals database connection, but no DependencySerializationTrait --> Drupal tries to serialize the Database connection and throws the error.

To solve the issue, I created my own decorator service class within a custom module, which extends the original decorator class from mail_login (because i need the logic from the mail_login decorator). I just added the DepenencySerializationTrait to my own decorator and replaced the service class for the decorator service in my modules service provider (in my case, the decorator service is called "mail_login.auth").

I'll share my code too.. (I modified it for the post, so there may be errors. But you can use the snippets for better understanding)

My decorator only uses DependencySerializationTrait:

<?php 

namespace Drupal\my_module;

use use Drupal\mail_login\AuthDecorator as MailLoginAuthDecorator;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;

class AuthDecoratorDependencyFix extends MailLoginAuthDecorator
{
  use DependencySerializationTrait;
}

My Serviceprovider just replaces the original service class:

<?php

namespace Drupal\my_module

use Drupal\Core\DependencyInjection\ContainerBuilder\ContainerBuilder;
use Drupal\my_module\AuthDecoratorDependencyFix;


class MyModuleServiceProvider 
{

  public function alter(ContainerBuilder $container) {
    if($container->hasDefinition('mail_login.auth')) {
      $mailLoginAuth = $container->getDefinition('mail_login.auth');
      $mailLoginAuth->setClass(AuthDecoratorDependencyFix::class);
    }
  }
}

I'll create an issue for the mail_login module (maybe on Monday ;)). Please let us know, if it's another service, or a completely different error on your side.

0

Found what caused the problem. As I said, it was working until recently and just stopped "without any reason". Then I remember that I recently installed module "Mail login": https://www.drupal.org/project/mail_login

And as soon as I uninstall that module everything is back to normal, everything works well.

So not sure where the problem is, probably inside that Mail login module, but they don't work well together.

Reported the issue here: https://www.drupal.org/project/mail_login/issues/3181217

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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