Ошибка Catalog::catchCatalogOrder() must be an instance

Некоторое время назад при добавлении товара в корзину на одном из сайтов стали получать ошибку:

[ErrorException] E_RECOVERABLE_ERROR
Argument 1 passed to Bitrix\Main\Analytics\Catalog::catchCatalogBasket() must be an instance of Bitrix\Main\Event, integer given (0)
/home/www/user/data/www/site.ru/bitrix/modules/main/lib/analytics/catalog.php:33
#0: Bitrix\Main\Analytics\Catalog::catchCatalogBasket(integer, array)

Никаким образом понять, в чем дело, и исправить ее не получалось. Я отписал в техподдержку Битрикса. Посоветовали обновить сайт, это не помогло. Затем переписали файлы ядра - это тоже никак не подействовало. Спросили нас, восстанавливали ли мы в последнее время сайт из резервной копии, этого не делали.

В итоге помог Лев Шестопалов, за что ему большое спасибо. Он отписал следующее: "Некорректный обработчик удалил из базы данных." После этого ошибка пропала и все заработало нормально.

Прошло какое-то время и мы уже успели забыть об ошибке, но неделю назад она снова возникла в другом виде. Теперь ошибка возникала при попытке оформить заказ и сообщала следующее:

[ErrorException] E_RECOVERABLE_ERROR
Argument 1 passed to Bitrix\Main\Analytics\Catalog::catchCatalogOrder() must be an instance of Bitrix\Main\Event, integer given (0)
/var/www/user/data/www/site.ru/bitrix/modules/main/lib/analytics/catalog.php:187
#0: Bitrix\Main\Analytics\Catalog::catchCatalogOrder(integer, array, array, boolean)

Я вспомнил, что уже было что-то похоже. Пошел искать обработчики на событие OnOrderSave. Нашел 3 обработчика, один из которых запускался из БД (судя по всему он и косячил).

Никакими методами API удалить этот обработчик мне не удалось. Решил тупо зайти в БД и удалить строчку с этим обработчиком. Как оказалось, хранилась строчка с ним в таблице b_module_to_module. После удаления строчки метод GetModuleEvents все равно возвращал мне этот обработчик, что означало только одно, он не удалился и все еще запускается. Да и ошибка не пропала.

В итоге я решил больше не тратить время на поиски решения и тупо снова написал в ТП. Там мне сообщили, что ошибка эта сама собой возникнуть не может, и скорее всего она возникла после того, как мы восстановили БД, но файлы не восстанавливали. (Как я понял в БД функция обработчика одна, а в файлах ожидается другая). Мы до возникновения ошибки никаких операций восстановления сайта не делали. Что привело к ошибке неизвестно.

Все тот же Лев Шестопалов любезно предоставил код, который исправляет данные ошибки. Привожу его ниже.

Сначала выполняем эти строки:
UnRegisterModuleDependences("sale", "OnBasketAdd", "main", "\\Bitrix\\Main\\Analytics\\Catalog", "catchCatalogBasket");
UnRegisterModuleDependences("sale", "OnOrderSave", "main", "\\Bitrix\\Main\\Analytics\\Catalog", "catchCatalogOrder");
UnRegisterModuleDependences("sale", "OnSalePayOrder", "main", "\\Bitrix\\Main\\Analytics\\Catalog", "catchCatalogOrderPayment");

UnRegisterModuleDependences("sale", "OnSaleBasketItemSaved", "main", "\\Bitrix\\Main\\Analytics\\Catalog", "catchCatalogBasket");
UnRegisterModuleDependences("sale", "OnSaleOrderSaved", "main", "\\Bitrix\\Main\\Analytics\\Catalog", "catchCatalogOrder");
UnRegisterModuleDependences("sale", "OnSaleOrderPaid", "main", "\\Bitrix\\Main\\Analytics\\Catalog", "catchCatalogOrderPayment");

После чего эти:
$eventManager = \Bitrix\Main\EventManager::getInstance();

$eventManager->registerEventHandler("sale", "OnSaleBasketItemSaved", "main", "\\Bitrix\\Main\\Analytics\\Catalog", "catchCatalogBasket");
$eventManager->registerEventHandler("sale", "OnSaleOrderSaved", "main", "\\Bitrix\\Main\\Analytics\\Catalog", "catchCatalogOrder");
$eventManager->registerEventHandler("sale", "OnSaleOrderPaid", "main", "\\Bitrix\\Main\\Analytics\\Catalog", "catchCatalogOrderPayment");
Иван Милов
Об авторе
Меня зовут Иван Милов, мне 28 лет. Опыт работы с Битрикс: 10 лет. Кроме этого работал с такими CMS, как Datalife Engine, WordPress, Joomla, OpenCart, Simpla и другими. Есть опыт парсинга и наполнения сайтов товарами и другими данными.