500 Internal Server Error: причины, логи и отличие от 502
500 Internal Server Error означает, что сервер столкнулся с непредвиденным сбоем при обработке запроса и сдался, не сообщив, что именно пошло не так. Это универсальная свалка среди кодов состояния HTTP, поэтому сам код почти не несет диагностической ценности, а настоящий ответ всегда находится в логах.
Почему 500 сообщает так мало
RFC 9110 определяет 500 как непредвиденное состояние, помешавшее серверу выполнить запрос. Это намеренно широкое определение. Все, чего приложение не предусмотрело - от обращения к null до сбоя подключения к базе данных или конфигурационного файла, который не удалось разобрать, - оказывается под одним и тем же номером.
Эта размытость - еще и защита. Страница 500 никогда не должна раскрывать публике стек-трейсы, пути файлов, фрагменты SQL или версии библиотек, потому что это как раз те детали, которые нужны атакующему. Поэтому код в ответе остается общим, а подробности уходят в лог, который можете прочитать только вы. Такой компромисс оправдан, и из-за него одно конкретное знание оказывается полезнее всех остальных: где лежат ваши логи.
500 против 502, 503 и 504
Все четыре - серверные ошибки, но их производят разные компоненты, и указывают они на разные проблемы. Разобраться в этом с самого начала экономит большую часть времени на отладку.
- 500 исходит от самого приложения. Что-то выполнилось и выбросило исключение. В логе приложения есть стек-трейс.
- 502 исходит от прокси перед приложением, который получил от бэкенда некорректный ответ или закрытое соединение. Сам бэкенд часто ничего не логирует, поскольку запрос так и не был завершен. См. руководство по 502.
- 503 - это отказ, а не крах. Сервер перегружен или на обслуживании и намеренно отклоняет работу, обычно с заголовком
Retry-After. - 504 - это таймаут. Бэкенд был доступен, но не ответил в пределах лимита прокси. Запрос часто продолжает выполняться где-то за кулисами.
Грубая шпаргалка: 500 значит, что сломался ваш код, 502 значит, что бэкенд мертв или ведет себя неправильно, 503 значит, что сервер намеренно отказывает, 504 значит, что бэкенд слишком медленный. Все семейство целиком сравнивается в обзоре 5xx.
Что вызывает 500
- Необработанные исключения в коде приложения. Самая большая отдельная категория. Значение null, неудачное преобразование типа, выход индекса массива за границы, деление на ноль на пути, который никто не тестировал.
- Сбои базы данных. Исчерпан пул соединений, сменились учетные данные, база данных перезапустилась, запрос попал в дедлок или таймаут.
- Отсутствующие или сломанные зависимости после деплоя. Пакет, который не установился, файл, который сборка не скопировала, переменная окружения, существующая на staging, но не в продакшене.
- Синтаксические ошибки конфигурации. В Apache одна-единственная неверная директива в файле
.htaccessдает 500 для каждого запроса в этом каталоге. - Права доступа и владелец файлов. Приложение не может прочитать конфигурационный файл или записать в каталог кэша, сессий или загрузок.
- Лимиты ресурсов. Лимит памяти, лимит времени выполнения или заполненный диск. Обычно это дает прерывистые 500, коррелирующие с трафиком.
- Сбои сторонних API, которые код вызывает без запасного варианта, поэтому чужой сбой становится вашей страницей ошибки.
Как диагностировать 500
- Убедитесь в коде и в том, кто его выдал. Брендированная страница ошибки может скрывать настоящий статус:
Проверьте строку статуса и любой заголовокcurl -sS -o /dev/null -D - https://example.com/failing-pageServerили CDN. Если ошибку подписывает граничная сеть, а источник отвечает 200, вы вообще смотрите не на 500 от своего приложения. - Сначала откройте лог приложения. Именно там находится стек-трейс. Логи фреймворка, поток логов платформы или stdout контейнера, в зависимости от вашего стека, и сопоставьте по времени и пути запроса.
- Затем лог ошибок веб-сервера.
error_logApache,error.lognginx или журнал событий Windows для IIS. Если приложение вообще ничего не залогировало, сбой произошел еще до выполнения вашего кода, что указывает на конфигурацию или среду выполнения. - Воспроизведите его намеренно. Установите, затрагивает ли 500 один URL, один метод HTTP, одного пользователя или все подряд. 500 только на POST обычно означает обработку формы или путь записи. 500 у одного пользователя обычно означает проблему в его данных.
- Включите подробные ошибки в непубличной среде. Никогда - в продакшене. Воспроизведите на staging с полным выводом ошибок, который превращает общий 500 в конкретный номер строки.
- Проверьте, что изменилось. Последний деплой, отправка конфигурации, продление сертификата, обновление зависимости или миграция базы данных. Если час назад сайт работал нормально, ответ почти всегда в последнем изменении.
- Проверьте ресурсы хоста. Место на диске, память и число соединений. Диск, забитый логами, дает 500, которые выглядят совершенно не связанными с кодом.
500, которые отдает только одна страница
Большинство 500 не кладут весь сайт. Ломается один маршрут, одна форма или один регион, пока главная страница продолжает загружаться, поэтому снаружи ничего не выглядит подозрительно, а ошибки всплывают спустя дни как потерянные регистрации. Запланированная HTTP-проверка важных страниц, а не только главной, сравнивает возвращаемый код с ожидаемым и оповещает в тот момент, когда маршрут начинает отвечать 500. Оповещения могут приходить по email, SMS, голосовым звонком, в Slack, Telegram и другими способами, так что ночной сбой доходит до дежурного, а не ждет утра. HostTracker следит за сайтами с 2004 года.