Есть особый жанр поломок: система исправно докладывает обо всём, кроме той проблемы, которая случилась прямо сейчас. Интеграция с CRM потеряла авторизацию, а сообщение об этом должно уйти через ту же CRM. Или у вас настроен красивый алерт в корпоративный мессенджер, но упал как раз токен этого мессенджера, и тишина выглядит как «всё хорошо». Дежурный спокойно пьёт чай, потому что тревог нет, а заявки тем временем копятся в очереди, которую никто не разбирает.

Эта статья о том, как построить мониторинг ошибок в n8n так, чтобы уведомление не зависело от того, что сломалось, и как после этого повторять выполнения, не плодя дубли. Вторая часть не менее важна первой: правильно разбуженный человек, который нажал не ту кнопку, способен причинить больше вреда, чем молчание.

Две цепочки, которые не должны делить одну жилу

Начнём с принципа, из которого вытекает всё остальное: рабочий workflow и маршрут сообщения об ошибке должны иметь как можно меньше общих зависимостей. Под зависимостью здесь понимается всё, что может отказать: учётные данные (credentials), внешний API, сетевой маршрут, лимиты, сам аккаунт сервиса.

Возьмём условный пример. Сценарий принимает заявки с сайта, создаёт сделку в CRM и отправляет менеджеру сообщение в рабочий чат. Если сообщение об ошибке отправляется в тот же чат тем же ботом с тем же токеном, то отказ чата одновременно ломает и работу, и сигнал о ней. Две цепочки превращаются в одну, и вы получаете единую точку отказа с красивой видимостью резервирования.

Разведение выглядит так:

  • Другой канал доставки. Если рабочие уведомления идут в мессенджер, сигнал об ошибке лучше отправлять почтой или в другой сервис, у которого свой аккаунт и свой набор учётных данных.
  • Другой credential. Даже если сервис тот же, отдельный бот или отдельный ключ только для алертов избавит вас от ситуации, когда отзыв одного токена глушит всё.
  • Отдельный получатель. Алерт, который уходит в общий шумный чат, тонет. Выделите место, где сообщения редкие и по делу.

Здесь стоит быть честным в одном месте: полной независимости внутри одного экземпляра n8n не получится. Об этом подробнее ниже, в разделе про остановку всего экземпляра. Пока важно другое: разведение по каналам и credentials закрывает самый частый класс «немых» отказов, когда ломается не n8n, а внешняя интеграция.

Что должно быть в сигнале, чтобы его можно было использовать

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

  1. Какой сценарий упал.
  2. Какое именно выполнение (чтобы сразу открыть нужную запись).
  3. На каком узле остановилось.
  4. Что это значит для работы: кто и что не получил.

Четвёртый пункт обычно забывают, а он решает, будить ли человека ночью. «Узел CRM вернул ошибку» и «новые заявки не попадают в CRM с 14:20, менеджеры их не видят» читаются совершенно по-разному, хотя речь об одном и том же событии.

Образец уведомления без секретов:

Сценарий: Заявки сайта → CRM
Выполнение: 48213
Упавший узел: Создать сделку
Сообщение: 401 Unauthorized
Влияние: новые заявки не попадают в CRM, менеджеры их не видят
Ссылка: адрес вашего n8n + путь к выполнению
Действие: проверить доступ к CRM, затем решить, повторять ли выполнение

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

Поле «Влияние» заполняется человеком заранее. Автоматически его не вычислить, но и не нужно: для каждого сценария достаточно одной фразы, которую вы один раз зашиваете в узел, формирующий сообщение, например по имени сценария. Это дешёвая работа, которая окупается при первом же инциденте.

Разберём, как это выглядит на практике. Допустим, общий обработчик обслуживает три сценария: заявки сайта, выгрузку счетов и ночную синхронизацию остатков. В узле, который собирает текст, лежит небольшая таблица соответствия «имя сценария — одна фраза о влиянии». Для заявок это «новые заявки не попадают в CRM, менеджеры их не видят», для счетов «клиенты не получают счета», для остатков «на сайте могут показываться вчерашние цифры». Три фразы пишутся за десять минут, а дежурный, получив сообщение в три часа ночи, сразу видит разницу между «подождёт до утра» и «нужно вставать».

Если имя сценария в таблице не нашлось, пусть сообщение всё равно уходит, а в поле влияния стоит честное «не описано». Такой текст сам напоминает, что у нового сценария нет описания последствий, и не даёт обработчику молча проглотить сбой из-за пропущенной строки.

Есть и обратное правило: не перегружайте сигнал. Каждая лишняя строка снижает шанс, что сообщение прочитают целиком. Если подробности нужны, они есть по ссылке на выполнение, а в сообщении должно хватать места ровно на решение «действовать сейчас или позже».

Error Trigger: один обработчик на много сценариев

Технически механизм в n8n устроен просто. Error workflow — это обычный workflow, который начинается с узла Error Trigger, а назначается он в настройках рабочего сценария. Когда назначенный сценарий завершается ошибкой, запускается этот обработчик и получает данные о сбое (документация n8n об обработке ошибок).

Важное следствие: один и тот же error workflow можно назначить нескольким сценариям. Для практики это означает, что формат сообщения, адресат и логика маршрутизации живут в одном месте. Не нужно копировать узел отправки в двадцать рабочих цепочек и потом вспоминать, в какой из них вы забыли обновить адрес.

Разумная схема для небольшой команды:

  • Один общий error workflow: Error Trigger, затем узел, собирающий текст по образцу выше, затем отправка по независимому каналу.
  • Назначение этого обработчика в настройках каждого боевого сценария. Это действие делается вручную для каждого сценария, поэтому новый workflow без назначения останется без сигнала. Включите проверку назначения в привычку выпуска, а не в память одного человека.
  • Если у части сценариев другие получатели (например, интеграции бухгалтерии разбирает другой человек), добавьте внутри обработчика ветвление по имени сценария, а не плодите обработчики.

Теперь о ловушке, ради которой этот раздел и написан. Сам error workflow — тоже код, который может сломаться. Если в нём упадёт отправка, никто об этом не узнает: сигнал о сбое сигнала некому доставить. Поэтому держите его максимально простым: минимум узлов, никаких обращений к тем же сервисам, что у рабочих сценариев, и обязательная проверка вручную после каждого изменения. Искусственно сломайте тестовый сценарий и убедитесь, что письмо дошло. Это одна из тех проверок, которые занимают пять минут и спасают от самой обидной тишины.

Есть и вторая тонкость: назначение error workflow задаётся для каждого рабочего сценария отдельно (документация n8n об обработке ошибок), поэтому полезно иметь постоянный тестовый сценарий, который специально падает, например на узле с заведомо неверным адресом. Его назначают тому же обработчику, и после любого изменения формата сообщения или канала вы запускаете его вручную и смотрите на результат. Так проверяется вся цепочка целиком: назначение, Error Trigger, сборка текста и доставка. Проверять только отправку отдельно недостаточно: можно убедиться, что письмо уходит, и не заметить, что обработчик ни к чему не подключён.

Заодно проверьте, что сообщение содержит именно те данные, которые вы ожидаете: имя сценария, номер выполнения, имя узла. Если после правки обработчика одно из полей стало пустым, лучше узнать об этом на тестовом падении, чем во время реального инцидента.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации Россия, США, Франция и Великобритания. Оплата картой РФ и по СБП.

АРЕНДОВАТЬ СЕРВЕР

Retry: что именно происходит при повторе

Алерт пришёл, причина устранена (например, обновили доступ к CRM). Естественное желание — нажать Retry на упавшем выполнении. Тут нужно понимать механику, иначе вместо починки получите дубли.

По документации, Retry продолжает сохранённое выполнение и не запускает всю цепочку заново с триггера. Упавший узел при этом повторно получает все свои элементы, в том числе те, которые были обработаны до сбоя (документация n8n о повторе выполнений).

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

Разбор на примере: пять заявок, третья упала

Условный пример. Триггер принял пакет из пяти заявок. Узел «Создать сделку в CRM» обрабатывает их по очереди. Первые две сделки созданы, на третьей CRM вернула ошибку, выполнение остановилось.

Что в этот момент реально произошло во внешнем мире? Две сделки существуют в CRM. Третья, четвёртая и пятая не созданы. А что видит n8n? Выполнение завершилось ошибкой на узле, и его входной набор — все пять элементов.

Нажимаем Retry. Узел снова получает все пять элементов. Первые две заявки он обработает ещё раз. Если CRM не защищается от повторов (нет уникального ключа, по которому она отвергнет вторую сделку с тем же внешним номером), в системе появятся две лишние сделки. Менеджеры позвонят клиентам дважды, и вы получите ровно тот результат, который хотели предотвратить.

Важно и то, чего Retry не гарантирует. Если защита от дублей была только в начале цепочки (например, в приёме вебхука или в проверке «видели ли мы такую заявку»), то при повторе она не обязана сработать: продолжение идёт с сохранённого состояния, а не с самого входа. Рассчитывать на то, что начальная дедупликация прикроет упавший узел, нельзя.

Вернёмся к тем же пяти заявкам и посмотрим на три возможных решения дежурного, когда причина уже устранена.

Пять заявок, третья упала: что даёт каждое действие
ДействиеЧто получит CRMИтог
Retry без сверки, защиты от повторов нетЗаявки 1–2 повторно, затем 3–5 впервыеДве лишние сделки, пять итоговых записей вместо трёх новых
Retry при уникальном внешнем номере заявки в CRMПовторы 1–2 отклонены или обновляют существующие записи, 3–5 созданыПять сделок, дублей нет, если CRM действительно проверяет ключ
Сверка, затем отдельная обработка заявок 3–5Только три недостающие заявкиПять сделок, но потребовалось ручное действие

Обратите внимание на первую строку: ошибка Retry тут не в самой кнопке, а в допущении, что она «доделает остаток». Упавший узел получает весь свой набор элементов заново (документация n8n о повторе выполнений), поэтому от того, умеет ли получатель отличать повтор от новой записи, зависит, окажется ли Retry исправлением или источником второго инцидента.

Дежурному это нужно знать до того, как он нажмёт кнопку. Практичный признак: если в сообщении об ошибке номер выполнения указывает на узел создания записи, а в CRM уже есть часть заявок из этого пакета, то повтор без сверки с высокой вероятностью дублирует их. Если упал узел чтения или запись по ключу, то та же частичная обработка безобидна.

Как сделать повтор безопасным

Варианты, от более надёжного к более ручному:

  • Идемпотентность на стороне получателя. Передавайте в CRM внешний идентификатор заявки и используйте возможность системы отклонять или обновлять запись с тем же ключом. Если такая возможность у конкретной CRM есть, повтор становится безвредным. Если её нет, этот вариант вам недоступен, и придумывать её за сервис не стоит. Заметим, что новый случайный идентификатор на каждой попытке защиты не даёт: он должен быть стабильным и привязанным к исходной заявке.
  • Проверка перед созданием. Внутри сценария перед узлом записи ставится запрос «есть ли уже сделка с этим номером заявки». Это лишний вызов, зато логика явная и работает при любом способе повтора.
  • Отметка обработанного. После успешной записи сценарий помечает заявку в собственной таблице или источнике, а перед записью отфильтровывает уже помеченные. Минус в том, что запись во внешнюю систему и отметка у вас не образуют единой атомарной операции: сбой между ними оставит заявку созданной, но не помеченной. Поэтому эту схему стоит сочетать с проверкой по внешнему номеру.
  • Ручная сверка перед Retry. Если защиты нет, перед повтором дежурный смотрит в CRM, какие заявки уже созданы, и принимает решение: повторять выполнение целиком, если дублей нет, или обработать оставшиеся заявки отдельно.

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

Какие повторы вообще безвредны

Полезно заранее разделить узлы по цене повторения. Это ваша классификация, а не свойство n8n, но она спасает в момент, когда решение нужно принять быстро.

Условная классификация узлов по риску повтора
Тип действияПримерРиск повтора
ЧтениеПолучить список заказовНизкий: повтор лишь заново прочитает данные
Запись с ключомОбновить карточку по внешнему номеруНизкий, если сервис действительно ищет запись по ключу
Создание записиНовая сделка, новый счётВысокий: возможны дубли
Сообщение человекуПисьмо клиенту, уведомление в чатВысокий: человек получит его повторно
Денежное или необратимое действиеСписание, отправка заказаКритический: сначала проверка во внешней системе

Когда падает узел из первых двух строк, Retry обычно безопасен. Когда из трёх последних, нужна сверка. Если вы знаете эту таблицу для своих сценариев заранее, то в алерт можно добавить строку «тип действия» и сэкономить дежурному минуту на размышления в самый неудобный момент.

Один сценарий упал и весь экземпляр лёг: это разные события

Теперь вернёмся к обещанному ограничению. Error workflow срабатывает, когда n8n жив и фиксирует ошибку конкретного выполнения. Если остановился сам экземпляр (процесс упал, закончилось место на диске, перегружен сервер, недоступна сеть), то обработчик, который живёт внутри этого же экземпляра, не запустится. Рассчитывать, что n8n сам сообщит о собственной полной недоступности, нельзя: сообщать некому.

Поэтому нужны два слоя наблюдения с разными задачами:

  • Внутренний слой — error workflow. Он отвечает на вопрос «какой сценарий сломался и почему». Он видит ошибки в логике и во внешних интеграциях.
  • Внешний слой — проверка снаружи, которая спрашивает: «жив ли экземпляр и отрабатывают ли сценарии вообще». Это может быть внешний сервис проверки доступности, обращающийся к адресу вашего n8n, или регулярный «пульс».

Про пульс стоит сказать отдельно, потому что он ловит самую коварную категорию: молчание. Если у вас есть сценарий, который должен срабатывать каждый час (по расписанию забирает данные), то отсутствие выполнений тоже авария, но Error Trigger её не заметит: ошибки же не было, выполнения просто нет. Решение — внешняя проверка по принципу «жду сигнала раз в час, не пришёл — тревога». Сценарий по успешному завершению отправляет короткий сигнал во внешний сервис мониторинга, а тот поднимает тревогу, если сигнала нет дольше допустимого. Конкретный сервис выбирайте сами, важен принцип: ожидающая сторона находится вне вашего экземпляра.

Распределение получается такое:

Какой слой ловит какую поломку
Что случилосьВнутренний error workflowВнешняя проверка
Узел вернул ошибку, n8n работаетВидитНе обязана видеть
Отозван токен интеграцииВидит как ошибку узлаНе видит, если экземпляр отвечает
Расписание перестало срабатывать без ошибокНе видитВидит по отсутствию пульса
Экземпляр недоступен целикомНе запускаетсяВидит по недоступности адреса

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

Где всё это лучше держать

Если n8n у вас на собственном сервере, у вас есть то, чего нет у облачных конструкторов: вы сами решаете, что стоит рядом с ним. Проверку доступности и пульс разумно держать вне машины с n8n, иначе вы вернётесь к исходной проблеме общей точки отказа. Размещение двух виртуальных серверов у одного провайдера само по себе не означает независимое оборудование или отказоустойчивость приложения, поэтому не принимайте второй VPS за автоматическое резервирование: если нужна реальная независимость, проверяйте её отдельно.

Для самого n8n на VPS MAATRIX доступны NVMe-диски, процессоры AMD EPYC и root-доступ; в каталоге есть предложение с n8n, а точное наличие и операционную систему стоит смотреть в форме заказа. Линейка тарифов начинается с Ba (1 vCPU, 2 ГБ RAM, 40 ГБ NVMe) и растёт до Djed (16 vCPU, 32 ГБ, 320 ГБ). Для небольшого набора интеграций с тихим error workflow обычно рассматривают младшие конфигурации, но выбор зависит от числа сценариев и размера обрабатываемых данных, и заранее его лучше проверить на своей нагрузке: ресурсы тарифа не равны обещанию конкретной ёмкости. О построении ИИ-цепочек на том же сервере можно прочитать в материале про ИИ-автоматизации в n8n на VPS.

Регламент дежурного: от тревоги до безопасного повтора

Соберём всё в последовательность действий, которую можно вписать в короткую памятку.

  1. Прочитать сигнал. Сценарий, выполнение, упавший узел, влияние. Если влияние критичное, действовать сразу; если нет, можно сначала разобраться без спешки.
  2. Определить класс поломки. Ошибка узла и работающий экземпляр — это внутренний сигнал. Тревога об отсутствии пульса или недоступности адреса — внешний, и начинать нужно с проверки самого сервера и процесса.
  3. Устранить причину. Обновить доступ, дождаться снятия лимита, исправить данные. Повторять выполнение, пока причина жива, бессмысленно: оно упадёт на том же узле.
  4. Посмотреть, какие элементы уже обработаны. Открыть выполнение и сопоставить входной набор упавшего узла с тем, что реально появилось во внешней системе.
  5. Выбрать действие по таблице риска. Чтение и запись по ключу повторять можно. Создание записей, письма людям и денежные операции — только после сверки внешнего результата.
  6. Повторить и проверить результат снова. После Retry убедиться в целевой системе, что нет дублей и ничего не потеряно.

Из этого перечня вытекает главная мысль всей статьи. Мониторинг заканчивается не тогда, когда пришло сообщение, а когда дежурный понимает, какое из действий допустимо повторить и где сначала проверить внешний результат. Сообщение без такого понимания лишь переносит тревогу в телефон, а Retry без сверки превращает один сбой в два. Если же сигнал приходит по независимому каналу, содержит нужные четыре строки, а повтор опирается на ключи и сверку, тишина в канале снова начинает означать, что всё в порядке.