Warning: session_start(): Cannot send session cache limiter - headers already sent (output started at /var/www/index.php:1)
#Что происходит
Функция session_start() отправляет заголовок cookie сессии и заголовки кэширования. HTTP-заголовки должны быть отправлены до начала тела ответа. Если любой вывод (даже один пробел или перевод строки) попал в ответ раньше, PHP не может добавить заголовки и выводит предупреждение с указанием файла и строки, где начался вывод: output started at /path/file.php:1. Это же объясняет ошибку Cannot modify header information для функций header() и setcookie(). Причины: пробелы вне тегов PHP, BOM в UTF-8 файле, echo до session_start, закрывающий тег ?> с пробелом после него, подключаемые файлы с выводом, включённый вывод ошибок до заголовков.
#Причины
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| Пробелы перед <?phpРедактор. | Вывод в строке 1. | Удалите. |
| BOM в UTF-8 файлеБлокнот. | Невидимый символ. | Сохраните без BOM. |
| echo до session_startПорядок. | Вывод выше. | Перенесите вызов. |
| Закрывающий тег с пробеломКонец файла. | Вывод в последней строке. | Уберите ?>. |
| Подключаемый файл выводит текстinclude. | Указан другой файл. | Исправьте его. |
| Сессия стартует дваждыПовтор. | Notice о сессии. | session_status(). |
#Порядок
- Прочитайте текст ошибки: в скобках указан файл и строка, где начался выводЭто могут быть РАЗНЫЕ ошибки:
Cannot send session cookie - headers already sentозначает, что HTTP-заголовки уже отправлены, аFailed to read session dataуказывает, например, на проблемы хранилища сессий. Сначала в закрытом журнале PHP найдите полный текст ошибки, временную метку, имя файла и строку. Не публикуйте содержимое сессионных данных или cookies. Если естьheaders already sent, выполните шаги 2–8; если ошибка чтения данных — начните сразу с проверкиsession.save_pathи обработчика сессий. - Откройте файл и уберите пробелы, пустые строки и любой текст до <?phpПри
headers already sentоткройте в редакторе указанный в сообщении PHP-файл и строку, где НАЧАЛСЯ вывод (после словoutput started at), а не только строкуsession_start(). Убедитесь, что до<?phpнет HTML, пробелов илиecho. Переместите формирование HTTP-заголовков и запуск сессии до вывода; не удаляйте видимый HTML из шаблона без оценки последствий. - Сохраните файлы в UTF-8 без BOMЕсли вывод начался в первой строке PHP-файла, проверьте его кодировку. В VS Code откройте файл → нажмите на отображаемую в нижней строке кодировку → «Сохранить с кодировкой» → «UTF-8» без BOM. В других редакторах название действия отличается. Перед изменением сохраните копию и проверьте, что русский текст и подключаемые файлы не повреждены. BOM — три невидимых байта до
<?php, которые могут отправить вывод. - Удалите закрывающий тег ?> в конце файлов, содержащих только PHP-кодВ файлах, содержащих только PHP-код, обычно не нужен завершающий
?>: откройте такой файл в редакторе, удалите его и пустые строки после него, сохраните и проверьтеphp -l путь/к/файлу. В шаблоне с HTML этот тег может быть частью разметки и удалять его не надо. Повторите запрос к странице, прежде чем менять следующие файлы. - Вызывайте session_start() в самом начале скрипта, до любого вывода и доОткройте основной PHP-контроллер и найдите место вызова
session_start(). Он должен выполняться после загрузки необходимых настроек и до любого HTML/echo, если сессия ещё не активна; при нескольких точках входа используйтеsession_status() === PHP_SESSION_NONE. Сохраните файл и проверьте, что заголовки Cookie в ответе корректны (F12 → «Сеть» → «Заголовки»); не оставляйте диагностический вывод данных сессии посетителям. - Убедитесь, что до этого не выводятся echo, print, var_dumpПоиск ранее отправленного вывода: в файлах, которые подключаются до
session_start(), найдитеecho,print,var_dump,die()и HTML вне PHP. Временно отключите лишь конкретный отладочный вывод на тестовом окружении и перезапустите запрос. Если ошибка исчезла, перенесите этот вывод после установки заголовков или замените серверным журналированиемerror_log()без секретов. - Включите буферизацию выводаБуферизация (
ob_start()илиoutput_buffering) может скрыть последствия раннего вывода, но НЕ исправляет ошибку чтения сессии. Используйте её только как осознанный временный приём в тестовой среде и не откладывайте устранение реальногоheaders already sent. При внедрении убедитесь, что приложение правильно завершает и отправляет буфер, иначе возникают лишнее потребление памяти и задержки. - Проверьте, что сессия не стартует дважды: используйте session_status()Проверьте, не вызывает ли приложение
session_start()повторно: в редакторе выполните поиск по проекту, затем убедитесь, что перед запуском стоитif (session_status() === PHP_SESSION_NONE). При необходимости используйте уже активную сессию, не запускайте её снова. Проверьте исходные сообщения PHP; если проблема в пользовательском обработчике сессий (Redis, БД), проверять нужно его подключение, а не BOM. - Проверьте права на каталог сессийПри
Failed to read session dataв администраторской среде откройте терминал веб-сервера и выполнитеphp -i | grep session.save_pathдля CLI, затем отдельно проверьте фактическую настройку PHP-FPM используемого сайта в панели/конфигурации (она может отличаться). Администратор должен проверить существование каталога, свободное место, доступ к файлам для пользователя PHP и ошибки обработчика в журнале. Не выполняйте рекурсивныйchmod 777и не заменяйте бездумно права системной директории; исправляйте только установленную первопричину. - Команды для отдельных ситуацийВыберите только подходящий вариант. Это не одна последовательность: часть команд диагностирует проблему, а часть меняет настройки или данные.
#Если ошибка идёт из чужого кода
В WordPress и других CMS такое предупреждение часто вызывает плагин или тема с пробелом перед <?php в functions.php. Строка из текста ошибки указывает на файл: откройте его и очистите. Для временного обхода переименуйте папку плагина и проверьте, пропала ли ошибка.