Если страница сайта не сохраняется, не нажимайте кнопку много раз и не начинайте сразу отключать все плагины. Сначала нужно понять, дошел ли запрос из браузера до приложения, какой ответ вернул сервер и записались ли изменения в базу. Одинаковый внешний симптом появляется при истекшей сессии, ошибке CSRF, блокировке WAF, превышении размера запроса, валидации поля, сбое редактора, конфликте расширения, нехватке места или ошибке SQL. У каждой причины свой способ проверки.
Правильная диагностика идет по цепочке: редактор формирует данные, браузер отправляет запрос, прокси и веб-сервер пропускают его, CMS проверяет права и поля, база фиксирует транзакцию, после чего интерфейс показывает сохраненную версию. Разрыв на любом шаге может выглядеть как бесконечная загрузка, молчаливое закрытие формы, сообщение «обновление не удалось», возврат старого текста после перезагрузки или успешное уведомление без фактических изменений.
Сначала сохраните текст и зафиксируйте симптом
До проверки скопируйте несохраненный текст в локальный документ без секретов и персональных данных. Если редактор поддерживает исходный HTML или JSON-блоки, сохраните их отдельно. Не обновляйте страницу, пока не выгружены данные формы и ответ проблемного запроса: после перезагрузки исчезнут JavaScript-ошибка, временный токен и содержимое Network. На рабочем сайте не очищайте кэш, таблицы ревизий и временные файлы до сохранения диагностических следов.
- запишите точное время ошибки с часовым поясом и адрес страницы в админке;
- укажите учетную запись и роль без передачи пароля;
- сохраните текст сообщения, а не только скриншот;
- отметьте, работает ли сохранение короткой тестовой страницы;
- проверьте, воспроизводится ли ошибка в другом браузере и у другого администратора;
- зафиксируйте последние изменения: обновление CMS, плагина, PHP, прокси или правил защиты;
- не публикуйте cookie, CSRF-токены, ключи API и полное содержимое пользовательских данных.
Полезно отдельно проверить «сохранить черновик», «обновить», «опубликовать» и автосохранение. Эти действия могут обращаться к разным endpoint и требовать разных прав. Если не работает только один режим, область поиска становится значительно уже.
Определите, что именно значит «не сохраняется»
Не объединяйте разные симптомы в одну ошибку. Кнопка может вообще не запускать запрос из-за JavaScript; запрос может быть отправлен и заблокирован до PHP; приложение может вернуть понятную ошибку валидации; база может откатить транзакцию; запись может сохраниться, но пользователь увидит старую копию из кэша. Для каждого варианта нужен наблюдаемый критерий.
- кнопка не реагирует: ищите ошибку JavaScript, перекрывающий элемент или неверное состояние формы;
- индикатор крутится бесконечно: проверяйте зависший HTTP-запрос, тайм-аут внешнего API и необработанное исключение;
- появляется 403: вероятны права, CSRF, WAF, ModSecurity или запрет метода;
- появляется 413: тело запроса больше лимита прокси или веб-сервера;
- появляется 419 или сообщение о сессии: истек токен или cookie не отправляется;
- появляется 422 или 400: сервер отклонил конкретные поля;
- появляется 500 или 502: проверяйте приложение, PHP-FPM, upstream и журнал ошибок;
- сервер отвечает успехом, но текст старый: сравнивайте базу, ревизию, кэш и читаемую реплику.
Проверка «у меня тоже не работает» недостаточна. Нужны URL запроса, метод, HTTP-код, короткий фрагмент ответа, request ID и состояние записи после операции. Эти данные позволяют отличить проблему интерфейса от проблемы хранения.
Посмотрите запрос сохранения в DevTools
Откройте инструменты разработчика до повторной попытки, выберите Network, включите сохранение журнала и отфильтруйте Fetch/XHR. Нажмите сохранение один раз. Найдите запрос по времени, endpoint или методу POST, PUT либо PATCH. Если запроса нет, переходите в Console и проверяйте первую ошибку JavaScript, а не десятки последующих сообщений.
- Откройте проблемную страницу и DevTools, не перезагружая ее после ошибки.
- В Network включите Preserve log и при необходимости Disable cache только для открытых DevTools.
- Повторите сохранение с минимальным безопасным изменением, например добавьте точку в черновик.
- Запишите Request URL, Request Method, Status Code, Duration и Content-Type ответа.
- В Payload проверьте, присутствуют ли идентификатор страницы, версия, заголовок и измененное поле.
- В Response или Preview найдите структурированную ошибку, код поля и request ID.
- В Timing определите, запрос долго отправляется, ждет сервер или не получает тело ответа.
- Сохраните HAR только после удаления cookie, Authorization, токенов и персональных данных.
Не делайте вывод только по зеленому статусу 200. Некоторые старые CMS возвращают HTML страницы входа с кодом 200, когда AJAX ожидал JSON. Некоторые обработчики ловят исключение и возвращают success до commit. Сверьте Content-Type, фактическое тело ответа и значение записи в базе или публичной версии после сброса только адресного кэша.
Проверьте сессию, cookie, CSRF и права пользователя
Редактор может оставаться открытым часами. За это время сессия истекает, CSRF-токен становится недействительным, а интерфейс продолжает показывать активную форму. После изменения домена, HTTPS, reverse proxy или SameSite-политики cookie может перестать попадать в AJAX-запрос. В результате страница входа открывается нормально, но сохранение получает 401, 403, 419 или HTML вместо JSON.
- сравните cookie в запросе страницы и в запросе сохранения без копирования их значений;
- проверьте Domain, Path, Secure и SameSite у сессионной cookie;
- убедитесь, что форма отправляет свежий CSRF-токен и приложение читает тот же источник;
- проверьте системное время браузера и сервера, если токен подписан и ограничен по времени;
- повторите вход в отдельной вкладке и затем безопасно перезагрузите копию редактора;
- сравните сохранение под другой ролью на тестовой странице;
- проверьте право на редактирование именно этой сущности, языка, сайта и статуса публикации.
Не решайте проблему отключением CSRF или выдачей всем пользователям роли супер-администратора. Это маскирует причину и создает уязвимость. Исправляют обновление токена, область cookie, доверенные proxy-заголовки, правила авторизации или обработку истекшей сессии. Интерфейс должен явно просить повторный вход и сохранять локальный черновик, а не молча терять данные.
Проверьте размер запроса и ограничения по количеству полей
Большая страница может сохраняться как один JSON, HTML или сотни полей конструктора. Короткий материал проходит, а длинный получает 413, пустой массив POST или обрезанный payload. Лимит может находиться в CDN, WAF, Nginx, Apache, PHP и самой CMS. Увеличение только post_max_size не поможет, если reverse proxy отклоняет тело раньше.
- сравните размер рабочего и проблемного Request Payload;
- проверьте client_max_body_size у Nginx и LimitRequestBody у Apache, если он задан;
- сопоставьте post_max_size и upload_max_filesize с реальным способом отправки;
- для форм с большим числом полей проверьте max_input_vars;
- учтите лимиты CDN, API gateway, ingress и облачного WAF;
- проверьте, не вставлено ли изображение как огромный data URI внутри HTML;
- не повышайте лимиты без оценки памяти, времени обработки и допустимого размера страницы.
После изменения лимита перезапустите только нужный сервис и проверьте эффективную конфигурацию, а не отредактированный файл. На сервере могут работать несколько версий PHP и несколько пулов PHP-FPM. Значение из CLI php -i не обязательно совпадает со значением веб-процесса. Для проверки используйте безопасную диагностическую страницу с ограниченным доступом или журнал запуска нужного пула, затем удалите диагностику.
Исключите блокировку WAF и защитных правил
Если ошибка зависит не от длины, а от конкретного слова, HTML-фрагмента, ссылки или кода, запрос может блокировать WAF. Правило способно принять CSS, SQL-пример, iframe, script, Base64 или сочетание параметров за атаку. При этом короткий нейтральный текст сохраняется, а материал с определенным фрагментом получает 403 или соединение обрывается.
- Создайте копию страницы или черновик на staging.
- Разделите проблемное содержимое пополам и найдите минимальный фрагмент, который вызывает блокировку.
- Сопоставьте время запроса с журналом WAF, ModSecurity, CDN или reverse proxy.
- Запишите идентификатор правила, endpoint и имя параметра без содержимого пользовательских данных.
- Сделайте узкое исключение для конкретного правила, маршрута и роли, если запрос действительно безопасен.
- Повторите негативный тест: опасные запросы по-прежнему должны блокироваться.
Полностью выключать WAF ради редактора не следует. Если правило ложно срабатывает на контент, исключение ограничивают endpoint сохранения, авторизованной ролью, конкретным параметром и методом. Защита входа, загрузки файлов и публичных форм должна остаться активной.
Найдите ошибку валидации или конфликт редактора
Современный редактор хранит блоки, связи, локали и служебные атрибуты. После обновления фронтенда формат payload может перестать соответствовать backend-схеме. Обязательное поле скрыто условием, идентификатор блока равен null, URL не проходит новый валидатор, а интерфейс не показывает ошибку. Иногда расширение браузера или оптимизатор JavaScript меняет DOM и обработчик отправляет устаревшее состояние.
- проверьте ответ 400/422 и привязку ошибки к полю;
- сравните JSON рабочего и проблемного черновика по структуре, не по персональному содержимому;
- проверьте обязательные поля во всех языковых версиях и вкладках;
- найдите дубли идентификаторов блоков после копирования страницы;
- проверьте корректность URL, даты, числа, категории и родительской страницы;
- повторите тест без браузерных расширений в чистом профиле;
- на staging временно отключайте плагины по одному, начиная с редактора, SEO, перевода и оптимизации;
- не отключайте расширения на рабочем сайте одновременно и без плана возврата.
Если страница состоит из блоков, удаляйте их только в копии и используйте деление пополам. Так быстрее находится один поврежденный блок или поле. После обнаружения сравните его схему с актуальной версией компонента и выполните штатную миграцию данных. Ручное удаление неизвестных полей из боевой базы может нарушить ревизии и связи.
Сопоставьте запрос с журналами приложения и веб-сервера
Клиентский ответ показывает границу, но не всегда причину. Найдите запрос в access log по времени, IP, пути и request ID. Затем сопоставьте его с error log веб-сервера, PHP-FPM, журналом CMS и базой. Если в инфраструктуре несколько узлов, проверьте именно тот instance, который обработал запрос. Иначе можно часами читать чистый журнал соседнего сервера.
# Примеры безопасного поиска после подстановки фактического времени и request ID grep '07/Aug/2026:10:3' /var/log/nginx/access.log grep 'request-id-from-response' /var/log/nginx/error.log journalctl -u php-fpm --since '10 minutes ago' # Не публикуйте строки с cookie, Authorization, паролями и содержимым формы- 403 без входа в приложение указывает на proxy, WAF или веб-сервер;
- upstream timed out указывает на долгую обработку PHP или внешнего сервиса;
- Allowed memory size exhausted требует поиска тяжелого этапа, а не только увеличения памяти;
- Maximum execution time exceeded показывает зависшую операцию или слишком большой объем;
- SQLSTATE и deadlock требуют проверки транзакции, индексов и конкурирующих записей;
- permission denied указывает на права каталога, временного файла или пользователя процесса;
- no space left on device требует проверки места и inode до любых повторных сохранений.
Логируйте технические идентификаторы, но не полное тело страницы. Для диагностики обычно достаточно page_id, user_id, request_id, версии документа, размера payload, этапа обработки и класса исключения. Содержимое редактора может включать персональные, коммерческие или закрытые данные.
Проверьте базу данных, диск и файловую систему
CMS может хранить основную запись в базе, изображения в объектном хранилище, временный черновик в файле, а индекс поиска в очереди. Ошибка одного зависимого шага иногда откатывает всю операцию. В другом варианте транзакция проходит, но приложение читает старую реплику или кэш. Поэтому нужно определить источник истины и проверить его сразу после одного контрольного сохранения.
- проверьте свободное место и inode на разделах базы, логов, tmp и uploads;
- убедитесь, что пользователь приложения может писать только в необходимые каталоги;
- проверьте состояние соединений, блокировок, deadlock и медленных запросов;
- сравните updated_at и версию записи до и после контрольного запроса;
- проверьте уникальные ограничения, внешние ключи и длину колонок;
- если есть read replica, прочитайте запись с primary или дождитесь подтвержденной репликации;
- проверьте доступность S3 или другого хранилища, если сохранение включает медиа;
- не запускайте массовый REPAIR, очистку таблиц или chmod 777 без доказанной причины.
При конфликте версий сервер должен вернуть 409 и предложить сравнение, а не молча перезаписать чужие изменения. Если два редактора работают параллельно, полезны номер версии, optimistic locking и история ревизий. Это отделяет настоящий сбой сохранения от защиты от потерянного обновления.
Убедитесь, что изменения не скрывает кэш
Иногда запись сохранена, но админка или публичная страница показывает старое значение. Причиной бывает объектный кэш, full-page cache, CDN, service worker, ISR/revalidate, кэш шаблона или чтение с отстающей реплики. Проверка через постоянное обновление браузера не доказывает, что источник данных старый: можно получать один и тот же закэшированный ответ.
- Проверьте updated_at и содержимое записи в источнике истины.
- Откройте API или preview, который читает страницу без публичного кэша.
- Посмотрите Age, X-Cache, Cache-Control, ETag и служебные заголовки CDN.
- Очистите или инвалидируйте только ключ этой страницы и связанных фрагментов.
- Проверьте, срабатывает ли событие очистки после commit, а не до него.
- Повторите запрос из чистого профиля и через curl без cookie, если страница публичная.
- Проверьте service worker и установленную PWA, если браузер отвечает из Cache Storage.
Не очищайте весь Redis, CDN и объектный кэш на загруженном проекте. Глобальная очистка создает всплеск нагрузки и стирает диагностическое различие между неверной записью и неверной инвалидацией. Адресный purge дает более надежный тест и меньше влияет на пользователей.
Пошаговый порядок безопасного исправления
Диагностику удобно вести от браузера к источнику данных. Каждый шаг должен отвечать на один вопрос и оставлять возможность возврата. Не меняйте одновременно лимиты, плагины, PHP и правила WAF: после такого набора невозможно понять, что исправило ошибку и не появилась ли новая.
- Сохраните несохраненный контент и создайте резервную копию затрагиваемой записи или staging-копию.
- Воспроизведите ошибку одним минимальным изменением и зафиксируйте время.
- В DevTools определите наличие запроса, endpoint, HTTP-код, тип ответа и request ID.
- Если запроса нет, исправьте первую JavaScript-ошибку и проверьте состояние формы.
- Если запрос отклонен до приложения, проверьте proxy, WAF, размер тела и метод.
- Если приложение вернуло ошибку, сопоставьте request ID с журналом и конкретным этапом.
- Проверьте сессию, CSRF, роль, данные формы и конфликт версии.
- Проверьте commit в базе, место на диске, права каталогов и зависимое хранилище.
- Если запись есть, проверьте реплику, ревизию и адресную инвалидацию кэша.
- Исправьте одну доказанную причину на staging и добавьте автоматический регрессионный тест.
- Внесите изменение в рабочую среду с резервной копией и планом отката.
- Проведите матрицу проверок для разных ролей, размеров страниц и способов сохранения.
Если проблема появилась после обновления, сначала сравните конфигурацию и миграции, а не откатывайте всю систему. Откат приложения без отката несовместимой схемы базы может ухудшить ситуацию. Безопасный возврат учитывает код, зависимости, структуру данных, кэш и формат сохраненных блоков.
Что проверить в популярных типах CMS
WordPress и блочные редакторы
Проверьте запросы REST API, nonce, права пользователя, размер JSON, PHP-журнал и конфликт плагинов редактора, безопасности, перевода или кэширования. Если проблема только у одной записи, ищите поврежденный блок, shortcode, метаполе или слишком большое число входных полей. Состояние Site Health полезно как ориентир, но не заменяет ответ конкретного REST-запроса.
1С-Битрикс
Сопоставьте запрос с журналом PHP, правами инфоблока, проверкой сессии, агентами и событиями обработчиков. Большие формы могут упираться в max_input_vars, а пользовательские обработчики OnBefore-событий способны отменить запись. Проверяйте результат обработчика и текст исключения, не отключая проверку сессии.
MODX, OpenCart и другие PHP-CMS
Проверьте логи менеджера и PHP, права каталога cache или storage, токен сессии, модификаторы и события расширений. Если сохранение зависит от магазина, языка или контекста, убедитесь, что передан правильный идентификатор. Очистку кэша выполняйте штатным способом и только после проверки фактической записи.
Название CMS помогает найти журнал и endpoint, но общий принцип одинаков: сначала наблюдаем запрос и ответ, затем проверяем авторизацию, обработчик, транзакцию и чтение результата. Не переносите готовый совет из другой версии CMS без проверки текущего стека.
Как проверить результат после исправления
Одна успешно сохраненная точка не завершает проверку. Нужно убедиться, что исправление работает для реальных размеров, ролей и режимов, не ослабило защиту и не сломало параллельное редактирование. Выполняйте тесты на копии материала или в согласованное окно, если они затрагивают публикацию.
- короткий черновик сохраняется и возвращает корректный структурированный ответ;
- длинная страница с типовым набором блоков сохраняется без обрезания;
- обновление и публикация работают только у разрешенных ролей;
- истекшая сессия показывает понятное сообщение и не теряет локальный текст;
- опасный запрос по-прежнему блокируется WAF;
- ошибка обязательного поля отображается рядом с полем, а не исчезает;
- updated_at, версия и содержимое меняются одной согласованной транзакцией;
- после сохранения preview и публичная страница получают новую версию в ожидаемый срок;
- два параллельных редактора получают контролируемый конфликт, а не молчаливую перезапись;
- логи не содержат cookie, токены и полный текст страницы;
- резервная копия или ревизия позволяет вернуть предыдущую версию.
Добавьте контрольный тест в тот слой, где была причина. Для лимита это запрос типового максимального размера; для WAF — безопасный контент и отдельный негативный пример; для CSRF — истекший и свежий токен; для базы — конфликт версии и откат; для кэша — проверка адресной инвалидации после commit.
Типичные ошибки при поиске причины
- много раз нажимать «Сохранить» и создавать конкурирующие запросы;
- обновлять страницу до копирования текста и фиксации Network;
- считать любой HTTP 200 успешным сохранением;
- увеличивать все лимиты PHP без измерения размера payload;
- отключать CSRF, WAF или проверку прав вместо узкого исправления;
- выдавать 777 каталогам ради устранения permission denied;
- отключать все плагины одновременно на рабочем сайте;
- очищать всю базу кэша до проверки источника истины;
- читать журнал не того PHP-пула или не того узла;
- передавать разработчику HAR с cookie и Authorization;
- откатывать код без учета миграций и формата блоков;
- проверять только под учетной записью супер-администратора.
Самое опасное временное исправление — убрать защитный слой, после чего сохранение начинает работать. Такой результат подтверждает область проблемы, но не является готовым решением. Нужно найти правило или условие, сделать минимальное исключение и повторить негативные тесты.
Как предотвратить повторение
Редактор должен быть спроектирован с учетом долгих сессий, больших документов, конфликтов и частичных отказов. Автосохранение не заменяет явную фиксацию версии, а сообщение «готово» должно появляться только после подтвержденной записи. Для критичных материалов полезны локальный черновик, серверные ревизии и возможность сравнить версии.
- возвращайте единый JSON-формат ошибок с request ID и кодом поля;
- показывайте состояние «изменено», «сохраняется», «сохранено» и точное время;
- не очищайте несохраненный текст при 401, 403, 409 или сетевой ошибке;
- контролируйте размер payload и количество блоков до отправки;
- используйте optimistic locking для параллельного редактирования;
- храните ревизии и регулярно проверяйте восстановление;
- проверяйте редактор на staging перед обновлением CMS и плагинов;
- добавьте мониторинг доли 4xx/5xx и p95 времени endpoint сохранения;
- связывайте браузерный request ID с веб-сервером, приложением и базой;
- документируйте лимиты proxy, PHP, WAF и самой CMS;
- логируйте метаданные операции без содержимого страницы и секретов.
После изменения инфраструктуры проводите короткий smoke-тест: вход, создание черновика, редактирование длинной страницы, загрузка разрешенного файла, публикация, preview и восстановление ревизии. Такой сценарий быстрее выявляет несовместимость, чем жалоба редактора после начала работы.
Когда нужна помощь с сохранением страницы
Если страница сайта не сохраняется и причина не видна по интерфейсу, я могу проследить один запрос от браузера до базы, сопоставить DevTools с логами, проверить сессию и CSRF, WAF, лимиты, PHP, обработчики CMS, транзакцию и кэш. Затем исправлю доказанную причину без отключения защиты, проверю разные роли и размеры страницы и оставлю понятный сценарий контроля. Для первичной диагностики достаточно адреса проблемной админ-страницы, времени ошибки, версии CMS, обезличенного HTTP-кода или request ID и списка последних изменений — пароли и содержимое закрытых материалов присылать не нужно.