Разборы

Ошибка 503 после обновления Битрикса: обновление установилось не целиком

После обновления Битрикса одна функция сайта перестала работать: форма с прикрепленным файлом отвечает "Произошла ошибка", остальное в порядке. Админка при этом пишет "система обновлена", версии модулей свежие. Причина оказалась в том, что обновление установилось не целиком: один модуль обновился, а файл другого модуля, который от него зависит, остался старым.

Случай разобран на коробочном Битрикс24, но механизм общий для сайтов на Битриксе.

Как это выглядело

Посетители заполняли форму CRM с полем "файл" и видели "Произошла ошибка". Запрос на загрузку файла получал ответ 503 с заголовком Retry-After: 600 и стандартной страницей "Упс... Похоже возникла ошибка в нашем программном коде".

503 вместе с Retry-After похоже на защиту от нагрузки или блокировку по IP, и это уводит в сторону. На самом деле так Битрикс отвечает на любую необработанную ошибку в коде.

Поломка кода или блокировка: три запроса

Все запросы форм идут через один адрес /bitrix/services/main/ajax.php, отличается только параметр action. Сравните три ответа:

ЗапросОтвет
проблемное действие503, фатальная ошибка
любое другое действие того же модуля200 и JSON с понятной ошибкой
заведомо несуществующее действие, например zzz.qqq200 и JSON "модуль не найден"

Если выдуманное действие обрабатывается нормально, а конкретное падает, это не блокировка и не защита, а поломка в коде именно этого действия.

Если сайт стоит за защитой от DDoS или CDN, повторите запрос по прямому адресу сервера. Одинаковый ответ и nginx в заголовке Server окончательно снимают подозрение с защиты.

Где искать текст ошибки

Путь к журналу задан в /bitrix/.settings.php, в секции exception_handling:

'log' => ['settings' => ['file' => '/home/bitrix/logs/php_error.log']],

Журнал пишется даже при выключенной отладке, включать ничего не нужно. Читайте его по SSH.

Не открывайте .settings.php через файловый менеджер админки: страница редактирования открывается пустой, и если нажать "Сохранить", файл обнулится вместе с настройками подключения к базе.

Причина

В журнале было:

FATAL - [ErrorException] E_COMPILE_ERROR
Declaration of Bitrix\Crm\Controller\Site\FileUploader::uploadAction(...)
must be compatible with Bitrix\UI\Controller\FileUploader::uploadAction(..., ?string $strategy = null)

Модуль ui обновился, и в его методе появился новый параметр. Файл модуля crm, который наследует этот метод, остался прежним. PHP отказывается собирать такой класс.

Проверяется по датам файлов:

ls -la bitrix/modules/crm/lib/controller/site/fileuploader.php \
       bitrix/modules/ui/lib/controller/fileuploader.php

Разница в датах была полтора года. Номера версий модулей при этом выглядели свежими: файл с версией обновился, а нужный файл кода нет. Поэтому ориентироваться на версии бесполезно, смотреть надо даты файлов.

Исправление

Привести объявление метода в наследнике в соответствие с родительским и передать новый параметр дальше в parent::. Перед правкой сохранить копию файла рядом.

Это правка в ядре. Следующее корректное обновление модуля ее перезапишет, и это правильно. Но если обновление снова не доедет, поломка вернется. Поэтому в техподдержку Битрикса писать все равно стоит: у них не установилось обновление файла, и то же самое может случиться у других.

Почему этого никто не заметил

В журнале нашлось около 400 таких ошибок за месяц. Посетители просто уходили. А в описании формы кто-то заранее дописал: "если после отправки вы получили сообщение об ошибке, отправьте документы на почту". То есть о проблеме знали, но обходили ее, вместо того чтобы искать причину.

Журнал ошибок стоит просматривать раз в месяц, а не только по жалобам. Обновление ядра раз за разом проходит без последствий, а потом один недоехавший файл месяц стоит вам заявок.

Что проверить у себя

  1. После каждого обновления пройти основные сценарии: заказ, формы с файлами, оплату, личный кабинет.
  2. Знать, где лежит журнал ошибок (exception_handling в .settings.php), и заглядывать в него.
  3. При ошибке 503 на одном действии сравнить его с соседними, а не искать блокировку.
  4. При подозрении на неполное обновление сравнивать даты файлов, а не версии модулей.

Если на вашем сайте после обновления что-то перестало работать, напишите мне. Обычно причина находится по журналу за час.

Похожая проблема на вашем сайте? Напишите в Telegram или оставьте заявку.