Гайды

Почему пользователи не видят сообщение об ошибке — 3 причины и как проверить

Иллюстрация: сообщение висит за пределами того, что видно на экране

Симптом всегда один и тот же: человек пишет «я нажал кнопку, ничего не произошло». Ты открываешь код — сообщение об ошибке есть. Проверяешь у себя — видно. Смотришь запись сессии — человек жмёт кнопку восемь раз подряд и уходит.

Ошибка отобразилась. Просто не там, не тогда или не так, чтобы её заметили. Разберём три причины по частоте — почти всегда это одна из них.

Причина 1: сообщение вне того, что видно на экране

Самая частая и самая незаметная в разработке.

Форма длинная. Поле «Почта» — вверху, кнопка «Отправить» — внизу. Человек жмёт, ошибка появляется у поля почты — на два экрана выше. Страница осталась на месте. Для человека не произошло вообще ничего.

У тебя это не воспроизводится, потому что на большом мониторе форма помещается целиком.

Как проверить. Открой форму, сожми окно браузера по высоте до размера телефона, прокрути к кнопке и отправь пустую форму. Если экран не сдвинулся — вот она, причина.

Как починить. После неудачной отправки прокрути страницу к первой ошибке и переведи туда фокус:

const firstInvalid = form.querySelector('[aria-invalid="true"]');
firstInvalid?.focus();                      // фокус сам прокрутит к элементу
firstInvalid?.scrollIntoView({ block: 'center', behavior: 'smooth' });

Именно фокус, а не только прокрутка: он одновременно решает задачу для клавиатуры и для скринридера. И ставить его надо на само поле, а не на текст ошибки — человеку сразу нужно печатать.

Причина 2: ошибка ушла в консоль, а не в интерфейс

Второй по частоте случай — и он почти всегда родом из кода, который писали быстро:

try {
  await api.save(data);
} catch (e) {
  console.error(e);   // ← весь UI об ошибке
}

Для тебя ошибка «есть»: она в консоли, ты её видишь при отладке. Для пользователя её не существует — консоль он не открывает никогда.

Как проверить. Найди в проекте все catch и посмотри, что внутри. Если там только console.error или пустые скобки — это молчаливая потеря:

grep -rn "catch" src/ | grep -v "setError"

Как починить. Правило: любой catch, который обрабатывает действие пользователя, обязан изменить состояние интерфейса. Не «залогировать», а изменить: сбросить спиннер, показать текст, вернуть кнопку в рабочее состояние.

Отдельная разновидность той же беды — когда запрос вообще не упал, но вернул не то, что ты ждал: сервер ответил 200, а в теле пусто. Тогда ошибки нет ни в консоли, ни в интерфейсе — типичная история неопределённого ответа. Проверяй не только catch, но и то, что пришло.

Причина 3: сообщение показалось и исчезло

Третий вариант — ошибку показали тостом на три секунды.

Человек в этот момент смотрел на кнопку, а плашка вылезла в правом верхнем углу. Или смотрел куда надо, но читает медленнее. Или это телефон, и плашка снизу накрыла кнопку — он ткнул ещё раз и закрыл её собственным нажатием.

Сюда же — случай, когда сообщение видно, но недоступно тем, кто пользуется скринридером. Блок, просто вставленный в разметку, озвучен не будет: чтобы его прочитали, нужна «живая область», которая лежит в разметке заранее и пустой, а текст появляется внутри неё:

<div id="form-status" role="status"></div>

Как проверить. Спроси у человека, который жаловался, одну вещь: «мелькнуло ли что-нибудь». Ответ «вроде что-то было, я не успел прочитать» — это точный диагноз.

Как починить. Ошибки формы не показывай тостом вообще — им место у поля. Разбор по критериям есть в тост или ошибка под полем. Если ошибка общая (упала сеть, сервер вернул 500) — оставь текст рядом с кнопкой, где он и останется до следующей попытки, а плашке сними таймер.

Если всё видно, а его всё равно не понимают

Бывает и четвёртый слой: сообщение на экране, человек его прочитал — и не понял, что делать.

Три частых виновника:

  • Цвет вместо текста. Красная рамка без подписи не читается ни скринридером, ни человеком, который не различает красный.
  • Слишком общая формулировка. «Ошибка валидации» не говорит, какое поле и что с ним не так. Нужно и то и другое: какое поле, что не так, каким должно быть.
  • Технический текст как есть. Unexpected token < in JSON at position 0 — это сообщение для тебя, а не для пользователя. Что оно означает, разбирается в как читать сообщение об ошибке; пользователю показывай человеческую фразу, а техническую убирай в логи.

Как проверить всё за одну минуту

Сожми окно браузера до высоты телефона. Отправь пустую форму. Не прокручивая, посмотри: экран сдвинулся к ошибке? Текст остался на месте через десять секунд? Понятно, какое поле чинить?

Три «да» — проблемы нет. Любое «нет» — ты нашёл свою причину.

Может, дело в CSS, и блок просто невидим?

Такое бывает: элемент есть в разметке, но скрыт стилями или спрятан за другим блоком. Проверяется в инспекторе за десять секунд — и, если да, это уже другая история про CSS.

Нужно ли показывать код ошибки пользователю?

Короткий идентификатор — полезно, если у тебя есть поддержка: человек назовёт его, и ты найдёшь запись в логах. Но идентификатор идёт после человеческого объяснения, а не вместо него.

Как отловить это заранее, без жалоб?

Считай в аналитике повторные нажатия одной кнопки за короткий промежуток. Три нажатия за пять секунд — почти всегда значит, что человек не получил обратной связи.

Учись вайб-кодингу, а не просто читай о нём

Короткие уроки-истории, симулятор агента и ежедневная практика — в нашем мобильном приложении. Бесплатно.

Открыть приложение
Робот KODiQ

ИИ-редактор KODiQ. Пишет про вайб-кодинг и AI-инструменты простым языком — каждый день.

Все статьи →