Типы ошибок протокола

STOMP.js работает поверх WebSocket (или SockJS), поэтому первый класс проблем возникает на уровне транспортного канала, ещё до обмена STOMP-фреймами. Эти ошибки не связаны с протоколом STOMP напрямую, но влияют на его поведение.

Основные сценарии:

Разрыв WebSocket-соединения

Соединение может быть закрыто по причинам, не связанным с приложением:

  • сетевые сбои
  • перезапуск брокера
  • закрытие соединения сервером по таймауту
  • блокировка соединения прокси или балансировщиком

В STOMP.js это проявляется через обработчики транспорта:

  • onWebSocketClose
  • onWebSocketError

При этом клиент уже не получает STOMP-фреймы, и все подписки становятся невалидными.

Ключевая особенность: протокол STOMP не успевает сообщить об ошибке через ERROR frame, потому что канал обрывается раньше.


Ошибки установления WebSocket handshake

Если сервер не принимает соединение:

  • неверный URL endpoint
  • отсутствие поддержки WebSocket
  • ошибки CORS при SockJS fallback
  • несовместимый upgrade handshake

Такие ошибки возникают до момента подключения STOMP-сессии, поэтому STOMP-клиент ещё не имеет sessionId.


Ошибки уровня STOMP-сессии

После успешного WebSocket handshake начинается STOMP negotiation. Здесь появляются ошибки протокола STOMP.

Неподдерживаемая версия протокола

STOMP требует согласования версии:

  • клиент отправляет accept-version
  • сервер отвечает поддерживаемой версией

Если пересечение версий отсутствует, сервер может разорвать соединение или вернуть ERROR frame.

Типичный сценарий:

  • клиент STOMP 1.2
  • сервер поддерживает только 1.0
  • соединение завершается без подписок

Ошибки CONNECT / CONNECTED

Фаза аутентификации и инициализации соединения.

Возможные причины ошибок:

  • неверные креденшелы (login / passcode)
  • отсутствие прав доступа к endpoint
  • отказ брокера в создании сессии
  • превышение лимита подключений

Сервер в этом случае может:

  • вернуть ERROR frame
  • или закрыть соединение без ответа

STOMP ERROR frame как основной механизм ошибок

Структура ERROR frame

STOMP протокол использует специальный фрейм:

  • command: ERROR
  • headers: содержат message, version, receipt-id
  • body: текст ошибки или сериализованные данные

STOMP.js обрабатывает такие сообщения через callback:

  • client.onStompError

Типовые причины ERROR frame

Ошибки авторизации

  • неправильный токен JWT
  • истекшая сессия
  • отсутствие прав на destination

Пример логики:

  • CONNECT успешен
  • SUBSCRIBE отклоняется через ERROR frame

Ошибки маршрутизации сообщений

Брокер может отклонить отправку:

  • несуществующий destination
  • запрещённый exchange/queue
  • некорректный формат маршрута

Серверные исключения

Если backend обработчик выбрасывает исключение, брокер может сформировать ERROR frame с диагностикой.

Особенность: такие ошибки часто содержат stack trace или внутренние сообщения системы, что требует фильтрации на клиенте.


Ошибки подписки (SUBSCRIBE)

Невалидный destination

Если клиент подписывается на:

  • несуществующий канал
  • защищённый endpoint
  • некорректный формат (например, отсутствие /topic/)

сервер может:

  • игнорировать подписку
  • или вернуть ERROR frame

Проблемы с идентификатором подписки

Каждая подписка имеет id. Ошибки возникают если:

  • id дублируется
  • id не передан
  • сервер требует уникальные идентификаторы в рамках сессии

Это часто приводит к некорректной маршрутизации сообщений или потере unSUBSCRIBE логики.


Ошибки отправки сообщений (SEND)

Перегрузка брокера

При высокой нагрузке брокер может:

  • отклонять сообщения
  • замедлять обработку
  • закрывать соединение

В STOMP это может проявляться как:

  • отсутствие подтверждений
  • разрыв соединения
  • ERROR frame с причиной overflow

Неверный формат сообщения

STOMP допускает передачу body как строку или бинарные данные (в зависимости от реализации). Ошибки возникают если:

  • нарушена сериализация JSON
  • отсутствует обязательный header (destination)
  • превышен лимит размера сообщения

Ошибки подтверждений (ACK / NACK)

При использовании клиентского подтверждения сообщений возникают специфические ошибки доставки.

ACK без активной транзакции

Если используется транзакционное подтверждение, но транзакция не открыта:

  • сервер может отклонить ACK
  • сообщение может быть повторно доставлено

NACK и повторная доставка

При NACK сообщение возвращается в очередь. Ошибки возникают если:

  • брокер не поддерживает повторную доставку
  • превышен лимит redelivery attempts
  • сообщение попадает в dead-letter queue

Ошибки heartbeat (контроль соединения)

STOMP 1.1+ поддерживает heartbeat механизм.

Потеря heartbeat

Если одна из сторон перестаёт отправлять heartbeat:

  • соединение считается “мертвым”
  • STOMP.js инициирует закрытие WebSocket
  • сервер может принудительно разорвать сессию

Причины:

  • блокировка event loop в браузере
  • перегрузка клиента
  • сетевые задержки

Несовместимость heartbeat интервалов

Если параметры heartbeat:

  • клиент: 10s/10s
  • сервер: 0/0 или 30s/30s

несогласованы, возможны:

  • ложные разрывы соединения
  • постоянные reconnection циклы

Ошибки receipt механизма

STOMP позволяет запрашивать подтверждение выполнения команд через receipt.

Потеря receipt

Если сервер не возвращает RECEIPT frame:

  • невозможно подтвердить доставку SEND / SUBSCRIBE
  • клиент может считать операцию неуспешной

Причины:

  • брокер не поддерживает receipts
  • ошибка на сервере при обработке команды
  • таймаут генерации ответа

Несоответствие receipt-id

Если receipt-id не совпадает с ожидаемым значением:

  • STOMP.js не может сопоставить ответ с запросом
  • операция считается неопределённой

Ошибки состояния клиента STOMP.js

Попытка операций без подключения

Частая категория ошибок:

  • send до connect
  • subscribe до установления session
  • unsubscribe после disconnect

Результат:

  • выброс исключения в STOMP.js
  • либо игнорирование операции

Повторное подключение (reconnect storm)

При автоматическом reconnect:

  • несколько попыток подключения одновременно
  • дублирование подписок
  • конфликт состояния клиента

Это приводит к:

  • дублированным сообщениям
  • нестабильной маршрутизации
  • ошибкам брокера из-за лимитов

Ошибки десериализации сообщений

Хотя STOMP передаёт данные как текст, приложения часто используют JSON.

Некорректный JSON payload

Типичные ситуации:

  • битый JSON
  • неожиданный формат (string вместо object)
  • несоответствие схемы данных

STOMP.js не валидирует payload, поэтому ошибка проявляется в бизнес-логике:

  • исключение при JSON.parse
  • потеря обработки сообщения
  • падение обработчика subscription callback

Ошибки конкурентного доступа к сессии

При параллельной работе с одним клиентом:

  • одновременные send/subscribe/unsubscribe
  • изменение headers в runtime
  • конфликт транзакций

Это может привести к:

  • race conditions в очередности фреймов
  • неконсистентному состоянию подписок
  • некорректным receipt mapping

Ошибки закрытия соединения

Нормальное закрытие

Фрейм DISCONNECT завершает сессию корректно, но ошибки возникают если:

  • отправка DISCONNECT не подтверждена
  • сервер закрывает соединение раньше ответа
  • клиент не успевает обработать финальные сообщения

Аварийное закрытие

Если соединение закрывается без DISCONNECT:

  • сервер не успевает отправить ERROR frame
  • клиент теряет контекст сессии
  • подписки считаются уничтоженными без уведомления

Ошибки брокер-специфичных расширений

Разные брокеры (RabbitMQ, ActiveMQ, Apollo) расширяют STOMP.

Несовместимость расширений

Ошибки возникают при:

  • использовании нестандартных headers
  • поддержке только части STOMP 1.2
  • различиях в ack mode

Ошибки преобразования сообщений брокером

Некоторые брокеры трансформируют сообщения:

  • изменение encoding
  • добавление headers
  • сериализация payload

При несовпадении ожиданий клиента возникают runtime ошибки обработки.