If a recurring order has been placed, then a subscription used by that order is deleted, going to the main Commerce > Orders page results in a WSOD with "The website encountered an unexpected error. Please try again later."

If the order that was placed is removed first, then the subscription removed, no errors.

It would be good for someone else to confirm this.

Steps to reproduce:

  1. Complete recurring order checkout
  2. Delete subscription used by that order
  3. Go to Orders page

Here's the error log:

Error: Call to a member function id() on null in Drupal\commerce_recurring\RecurringOrderManager->collectSubscriptions() (line 184 of /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/modules/contrib/commerce_recurring/src/RecurringOrderManager.php) #0 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/modules/contrib/commerce_recurring/src/RecurringOrderManager.php(75): Drupal\commerce_recurring\RecurringOrderManager->collectSubscriptions(Object(Drupal\commerce_order\Entity\Order)) #1 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/modules/contrib/commerce_recurring/src/RecurringOrderProcessor.php(35): Drupal\commerce_recurring\RecurringOrderManager->refreshOrder(Object(Drupal\commerce_order\Entity\Order)) #2 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/modules/contrib/commerce/modules/order/src/OrderRefresh.php(155): Drupal\commerce_recurring\RecurringOrderProcessor->process(Object(Drupal\commerce_order\Entity\Order)) #3 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/modules/contrib/commerce/modules/order/src/OrderStorage.php(92): Drupal\commerce_order\OrderRefresh->refresh(Object(Drupal\commerce_order\Entity\Order)) #4 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/core/lib/Drupal/Core/Entity/EntityStorageBase.php(389): Drupal\commerce_order\OrderStorage->doPreSave(Object(Drupal\commerce_order\Entity\Order)) #5 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php(796): Drupal\Core\Entity\EntityStorageBase->save(Object(Drupal\commerce_order\Entity\Order)) #6 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/core/lib/Drupal/Core/Entity/Entity.php(377): Drupal\Core\Entity\Sql\SqlContentEntityStorage->save(Object(Drupal\commerce_order\Entity\Order)) #7 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/modules/contrib/commerce/modules/order/src/OrderStorage.php(114): Drupal\Core\Entity\Entity->save() #8 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/core/lib/Drupal/Core/Entity/EntityStorageBase.php(249): Drupal\commerce_order\OrderStorage->postLoad(Array) #9 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/core/modules/views/src/Plugin/views/query/Sql.php(1563): Drupal\Core\Entity\EntityStorageBase->loadMultiple(Array) #10 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/core/modules/views/src/Plugin/views/query/Sql.php(1488): Drupal\views\Plugin\views\query\Sql->loadEntities(Array) #11 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/core/modules/views/src/ViewExecutable.php(1423): Drupal\views\Plugin\views\query\Sql->execute(Object(Drupal\views\ViewExecutable)) #12 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/core/modules/views/src/ViewExecutable.php(1451): Drupal\views\ViewExecutable->execute(NULL) #13 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/core/modules/views/src/Plugin/views/display/Page.php(171): Drupal\views\ViewExecutable->render() #14 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/core/modules/views/src/ViewExecutable.php(1627): Drupal\views\Plugin\views\display\Page->execute() #15 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/core/modules/views/src/Element/View.php(77): Drupal\views\ViewExecutable->executeDisplay('page_1', Array) #16 [internal function]: Drupal\views\Element\View::preRenderViewElement(Array) #17 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/core/lib/Drupal/Core/Render/Renderer.php(378): call_user_func(Array, Array) #18 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/core/lib/Drupal/Core/Render/Renderer.php(195): Drupal\Core\Render\Renderer->doRender(Array, false) #19 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(226): Drupal\Core\Render\Renderer->render(Array, false) #20 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/core/lib/Drupal/Core/Render/Renderer.php(576): Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() #21 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(227): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure)) #22 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(117): Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\CurrentRouteMatch)) #23 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/core/lib/Drupal/Core/EventSubscriber/MainContentViewSubscriber.php(90): Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\CurrentRouteMatch)) #24 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php(108): Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object(Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent), 'kernel.view', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher)) #25 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/vendor/symfony/http-kernel/HttpKernel.php(158): Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch('kernel.view', Object(Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent)) #26 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/vendor/symfony/http-kernel/HttpKernel.php(68): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1) #27 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/core/lib/Drupal/Core/StackMiddleware/Session.php(57): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #28 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(47): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #29 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(99): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #30 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(78): Drupal\page_cache\StackMiddleware\PageCache->pass(Object(Symfony\Component\HttpFoundation\Request), 1, true) #31 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(47): Drupal\page_cache\StackMiddleware\PageCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #32 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(50): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #33 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #34 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/core/lib/Drupal/Core/DrupalKernel.php(657): Stack\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #35 /home/mhubbard/Dev/acromediainc/commerce-2-demo/commerce-2-demo/web/index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request)) #36 {main}.

Comments

Hubbs created an issue. See original summary.

focal55’s picture

Testing with:
Commerce 2.x-dev
Commerce Recurring 2.x-dev

I am noticing a similar symptom rooted in the collectSubscriptions() function. In my testing I am noticing the isEmpty() function is return TRUE even though the field has values.

<?php
public function collectSubscriptions(OrderInterface $order) {
// ...
// This is returning TRUE even though the field has a value.
if ($order_item->get('subscription')->isEmpty()) {
// ...
}
?>

Also, I have experience the following statement return NULL:

<?php
// ...
// $subscription is set to NULL in this statement.
$subscription = $order_item->get('subscription')->entity;
?>

I am not sure why these statements are not working as expected. Possibly something with out the ->entity method is being used. I have reworked these two statements in the attached patch which seem to produce better results.

bojanz’s picture

Title: Deleting subscription used by order results in WSOD when viewing Order page » Guard against deleted subscriptions in RecurringOrderManager
Version: 8.x-1.0-beta2 » 8.x-1.x-dev

  • bojanz committed 3c36d44 on 8.x-1.x
    Issue #2932805 by focal55, Hubbs, bojanz: Guard against deleted...
bojanz’s picture

Status: Active » Fixed

Pushed a fix, thanks everyone.

heddn’s picture

I wonder if this has caused a regression. I'm going to test further.

heddn’s picture

No, it hasn't. However, there does seem to be a DB race condition where during initial subscription creation, the subscription is created, assigned an id, but when checking the db directly, the commerce_subscription table isn't populated yet. Not until everything is committed. Then is shows up. By which time it is too late. And the line item's 'subscription' is NULL. So renewal's fail. I'll keep looking or open a follow-up.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

pyxio’s picture

this issue is not fixed. it happens to me when manually creating an order for a user whose order was previously deleted. so i think status should not be fixed. i have tried 8.x-1.x-dev too and same issue.