После обновления Битрикса одна функция сайта перестала работать: форма с прикрепленным файлом отвечает "Произошла ошибка", остальное в порядке. Админка при этом пишет "система обновлена", версии модулей свежие. Причина оказалась в том, что обновление установилось не целиком: один модуль обновился, а файл другого модуля, который от него зависит, остался старым.
Случай разобран на коробочном Битрикс24, но механизм общий для сайтов на Битриксе.
Как это выглядело
Посетители заполняли форму CRM с полем "файл" и видели "Произошла ошибка". Запрос на загрузку файла получал ответ 503 с заголовком Retry-After: 600 и стандартной страницей "Упс... Похоже возникла ошибка в нашем программном коде".
503 вместе с Retry-After похоже на защиту от нагрузки или блокировку по IP, и это уводит в сторону. На самом деле так Битрикс отвечает на любую необработанную ошибку в коде.
Поломка кода или блокировка: три запроса
Все запросы форм идут через один адрес /bitrix/services/main/ajax.php, отличается только параметр action. Сравните три ответа:
| Запрос | Ответ |
|---|---|
| проблемное действие | 503, фатальная ошибка |
| любое другое действие того же модуля | 200 и JSON с понятной ошибкой |
заведомо несуществующее действие, например zzz.qqq | 200 и 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 таких ошибок за месяц. Посетители просто уходили. А в описании формы кто-то заранее дописал: "если после отправки вы получили сообщение об ошибке, отправьте документы на почту". То есть о проблеме знали, но обходили ее, вместо того чтобы искать причину.
Журнал ошибок стоит просматривать раз в месяц, а не только по жалобам. Обновление ядра раз за разом проходит без последствий, а потом один недоехавший файл месяц стоит вам заявок.
Что проверить у себя
- После каждого обновления пройти основные сценарии: заказ, формы с файлами, оплату, личный кабинет.
- Знать, где лежит журнал ошибок (
exception_handlingв.settings.php), и заглядывать в него. - При ошибке 503 на одном действии сравнить его с соседними, а не искать блокировку.
- При подозрении на неполное обновление сравнивать даты файлов, а не версии модулей.
Если на вашем сайте после обновления что-то перестало работать, напишите мне. Обычно причина находится по журналу за час.