Workflow может отработать без технического сбоя, но получить непригодные данные: сумму строкой, пустого клиента или повтор заказа. Просто отфильтровать неверную запись не всегда достаточно: иногда нужно отклонить весь пакет. Настроим в n8n явную остановку с сообщением, по которому понятно, что исправить.
Результат инструкции
Один item содержит orders из трёх заказов. Check Batch сначала проверяет весь массив. Если всё правильно, IF направляет пакет в Preview Ready: получаем ID заказов, количество и сумму для ручной проверки. Если хотя бы один заказ неверный, пакет идёт в Stop Invalid Batch и запуск завершается ошибкой с номером строки и кодом причины.
Правило «весь пакет или ничего» реализовано нашей проверкой до ветвления. Сам Stop And Error не проверяет заказы: он завершает запуск, когда управление дошло до него. Внешних записей здесь нет. action_performed всегда false; ни деньги, ни письма, ни CRM схема не затрагивает. AI-модель также не нужна.
Что понадобится
- Работающий n8n и возможность создать отдельный учебный workflow. Проверено на n8n 2.42.4, Stop And Error версии 1, IF версии 2.2.
- Только вымышленные заказы из примера. Не подставляйте реальные персональные данные и секреты.
- Никаких API-ключей, внешних интеграций и платной модели.
Установка n8n локально через Docker
Шаг 1. Импортируйте готовую схему
Скачать n8n-stop-invalid-batch.json
Создайте новый workflow. В меню редактора выберите Import from File и загрузите JSON. Если файл открылся текстом, сохраните его и импортируйте. На полотне будут шесть узлов:
Manual Trigger → Sample Batch → Check Batch → Batch OK
true → Preview Ready
false → Stop Invalid Batch
Sample Batch, Check Batch и Preview Ready — Code. Batch OK — IF. Stop Invalid Batch — Stop And Error. При ручной сборке используйте точно эти имена. Файл не содержит credentials и ID чужого workflow, остаётся неактивным. Для ручного запуска публиковать его не нужно.
Шаг 2. Подготовьте один пакет из трёх заказов
В Sample Batch задайте Mode: Run Once for All Items, Language: JavaScript. Вставьте:
const orders = [
{
"order_id": "O1",
"client": "Анна",
"amount_minor": 150000
},
{
"order_id": "O2",
"client": "Борис",
"amount_minor": 0
},
{
"order_id": "O3",
"client": "Альфа",
"amount_minor": 49900
}
];
return [{ json: { orders } }];
Запустите источник от Manual Trigger. В Output должен быть один item с orders из трёх объектов, не три отдельных items. Все суммы заданы целыми копейками: 150000, 0 и 49900. Итого 199900 копеек, или 1999 рублей. Нулевую сумму считаем допустимой, а пустое значение — ошибкой.
Мы специально собираем весь набор в одном item, чтобы принять одно решение о пакете до следующего действия. Если ваш источник возвращает отдельные items, сначала соберите согласованный массив и проверьте полноту выгрузки. Этот пример не объединяет страницы API и не координирует параллельные запуски.
Шаг 3. Проверьте пакет без преждевременной отправки
В Check Batch выберите Run Once for All Items и JavaScript. Вставьте код целиком, включая конец блока:
Показать код (34 строк)
const items = $input.all();
const errors = [];
const add = (row, code) => errors.push({ row, code });
const orders = items.length === 1 ? items[0].json.orders : undefined;
const ids = new Set();
let total = 0;
if (!Array.isArray(orders)) add(0, 'orders_array_required');
else if (!orders.length) add(0, 'orders_empty');
else for (let i = 0; i < orders.length; i++) {
const row = orders[i];
if (!row || typeof row !== 'object' || Array.isArray(row)) {
add(i + 1, 'order_object_required');
continue;
}
if (typeof row.order_id !== 'string' || !row.order_id.trim() || ids.has(row.order_id)) {
add(i + 1, 'order_id_missing_or_duplicate');
} else ids.add(row.order_id);
if (typeof row.client !== 'string' || !row.client.trim()) add(i + 1, 'client_required');
if (!Number.isSafeInteger(row.amount_minor) || row.amount_minor < 0) {
add(i + 1, 'amount_minor_invalid');
} else {
total += row.amount_minor;
if (!Number.isSafeInteger(total)) add(i + 1, 'total_out_of_range');
}
}
const valid = errors.length === 0;
return [{ json: {
valid,
errors,
orders: valid ? orders.map(({ order_id, client, amount_minor }) => ({ order_id, client, amount_minor })) : [],
count: Array.isArray(orders) ? orders.length : 0,
total_amount_minor: valid ? total : null,
error_message: valid ? '' : 'batch_invalid: ' + errors.map(e => 'row ' + e.row + ' ' + e.code).join('; '),
} }];
Код не бросает ошибку при первой неверной сумме. Он собирает причины в errors и возвращает один результат проверки. Это позволяет направить его в специальный Stop And Error. row считается с единицы; row 0 обозначает ошибку структуры всего пакета. Поля внутри ошибки — номер позиции и заранее заданный код, без имён клиентов и исходных значений.
| Поле | Допустимое значение | Ошибка |
|---|---|---|
| orders | Непустой массив | orders_array_required или orders_empty |
| Элемент массива | Объект заказа | order_object_required |
| order_id | Непустая уникальная строка | order_id_missing_or_duplicate |
| client | Непустая строка | client_required |
| amount_minor | Неотрицательные целые копейки | amount_minor_invalid |
Проверяется также безопасный целочисленный диапазон общей суммы: его переполнение даёт total_out_of_range. Если есть хотя бы одна ошибка, orders на выходе Check Batch становится пустым, а total_amount_minor — null. Это выбранное правило примера, не удаление входных данных из истории n8n.
Шаг 4. Настройте IF по логическому valid
В Batch OK добавьте одно условие. Слева включите Expression и вставьте:
{{ $json.valid }}
Тип условия: Boolean, операция is true. Преобразование типов автоматически не включайте; в готовой схеме type validation strict. На вход IF приходит логический true или false, не строки "true" и "false". При верных заказах должен сработать выход true, при неверных — false.
Подробная инструкция по IF и двум веткам
Шаг 5. Подключите предпросмотр к выходу true
Соедините выход true Batch OK с Preview Ready. В этом Code задайте Run Once for All Items, JavaScript и вставьте:
const items = $input.all();
if (items.length !== 1) throw new Error('preview_requires_valid_batch');
const row = items[0].json;
if (row.valid !== true || !Array.isArray(row.errors) || row.errors.length ||
!Array.isArray(row.orders) || !row.orders.length || row.count !== row.orders.length) {
throw new Error('preview_requires_valid_batch');
}
return [{ json: {
status: 'ready_for_review',
count: row.count,
order_ids: row.orders.map(order => order.order_id),
total_amount_minor: row.total_amount_minor,
action_performed: false,
} }];
В начале есть дополнительная проверка valid, errors и длины массива. Она замечает ошибочную маршрутизацию, если неверный пакет случайно отправили на ветку предпросмотра. Это проверка внутреннего результата Check Batch, а не универсальный валидатор любых данных из сети. Не подключайте источник напрямую к Preview Ready.
Предпросмотр не равен выполненному действию. status ready_for_review означает только готовность учебной сводки к просмотру. action_performed false показывает, что ничего во внешнюю систему не записано.
Шаг 6. Подключите Stop And Error к выходу false
Добавьте Stop And Error, назовите его Stop Invalid Batch и соедините только с выходом false Batch OK. В Error Type выберите Error Message. Для Error Message включите Expression:
{{ $json.error_message }}
В предпросмотре выражения при ошибочном входе должен быть готовый текст batch_invalid с причиной, а не буквальные фигурные скобки. В экспортированном JSON выражение начинается со служебного =; готовый файл уже оформлен правильно.
У Stop And Error нет обычного выходного соединения: это конец ошибочной ветки. Не нужно рисовать продолжение после него или соединять ветки обратно через Merge. Режим Error Object здесь не используется и в этой инструкции не тестировался.
Шаг 7. Оставьте остановку при ошибках
В Settings Stop Invalid Batch задайте On Error: Stop Workflow. Не включайте Retry On Fail для заведомо неверных данных: повторный запуск не превратит строковую сумму в число. В Code и IF также оставьте Stop Workflow, Execute Once и Always Output Data выключены.
В этой схеме мы не используем Continue On Error или подмену ошибочного результата успешным. Внешние действия должны находиться после проверки, не до неё и не в параллельной ветке. Stop And Error не откатывает уже отправленные письма, созданные записи и списания. Если действие случилось раньше, одна ошибка n8n его не отменит.
Шаг 8. Выполните корректный пакет
Нажмите Execute Workflow и откройте Preview Ready. Ожидается один item:
{
"status": "ready_for_review",
"count": 3,
"order_ids": [
"O1",
"O2",
"O3"
],
"total_amount_minor": 199900,
"action_performed": false
}
Сверьте count 3, порядок O1/O2/O3 и total_amount_minor 199900. В Check Batch должны быть valid true, errors пустой массив, error_message пустая строка. Stop Invalid Batch при таком запуске не выполняется. Это и есть правильное разделение веток, а не ошибка пропущенного узла.
Шаг 9. Сломайте одну сумму и проверьте остановку всего пакета
В Sample Batch у O2 временно замените amount_minor: 0 на amount_minor: "0", то есть сделайте число строкой. Сохраните изменение и выполните весь workflow от триггера. Ожидается ошибка на Stop Invalid Batch:
batch_invalid: row 2 amount_minor_invalid
В Check Batch должны быть valid false, count 3, orders пустой массив и одна причина с row 2. false-выход IF получает результат проверки; Preview Ready в этом запуске не должен выполняться. Корректные O1 и O3 не проходят отдельно: пакет отвергнут целиком.
Не смотрите старый зелёный Output от предыдущего запуска как доказательство успеха. Откройте текущий execution и сверьте время, ошибочный узел и отсутствие свежего Preview Ready. Исправление должно начинаться со входа и нового полного запуска, а не с ручного исполнения следующего узла на сохранённых данных.
Шаг 10. Проверьте пустой пакет и несколько причин
Верните у O2 число 0. Затем в Sample Batch временно задайте const orders = []; и запустите workflow. Ожидается batch_invalid: row 0 orders_empty. Источник специально возвращает item даже при пустом массиве, поэтому Check Batch и Stop And Error смогут выполниться. Это не то же самое, что источник, вернувший ноль items.
Верните три заказа. У O1 задайте client пустой строкой, у O3 amount_minor строкой "x". В результате должны быть две причины: row 1 client_required и row 3 amount_minor_invalid. Исправьте обе, а не только первую. Имена и содержимое заказа в error_message не добавляются.
| Опыт | Результат запуска | Предпросмотр |
|---|---|---|
| Три корректных заказа | Успех, сумма 199900 | Есть |
| Строка "0" у O2 | Ошибка row 2 amount_minor_invalid | Нет |
| orders: [] | Ошибка row 0 orders_empty | Нет |
Шаг 11. Проверьте неправильное условие на копии
Создайте копию учебного workflow. Оставьте строковую сумму "0" у O2. В Batch OK временно замените левое выражение на {{ true }}, чтобы принудительно направить неверный пакет на true-выход. Preview Ready должен остановиться с preview_requires_valid_batch. Stop Invalid Batch в этом опыте не выполняется, потому что IF выбрал другую ветку.
Этот тест проверяет дополнительную защиту в нашем Code, не способность Stop And Error перехватывать все ошибки схемы. Верните условие {{ $json.valid }}. Не переносите экспериментальные настройки в рабочий workflow и не подключайте к копии реальные действия.
Шаг 12. Восстановите и сохраните рабочую схему
Верните три исходных заказа, числовые суммы, непустых клиентов и IF по valid. Проверьте два соединения: true → Preview Ready, false → Stop Invalid Batch. Сохраните и выполните полный запуск. Снова должны получиться count 3, сумма 199900, ready_for_review и action_performed false.
Оставьте workflow ручным и неактивным. Для применения к реальному источнику отдельно согласуйте допустимость пустого пакета, точные типы, доступ и хранение executions. Решите также, отклонять ли весь пакет или отправлять неверные записи на отдельную проверку. Здесь сознательно выбран первый вариант.
Если результат отличается
| Симптом | Причина | Что проверить |
|---|---|---|
| Неверный пакет завершился успешно | False-ветка не ведёт в Stop | Соединения и текущий execution |
| В ошибке фигурные скобки | Сообщение осталось Fixed | Expression в Error Message |
| Строка "0" отклоняется | Требуется именно число | Кавычки у amount_minor |
| Пустой источник не вызвал проверку | Не пришло ни одного item | Возвращается ли объект с orders: [] |
| Предпросмотр даёт preview_requires_valid_batch | Неправильный маршрут | Условие IF и вход Check Batch |
Как связать с обработкой ошибок
Stop And Error задаёт явный неуспех текущего запуска. Журналирование и уведомления — отдельная задача. Для неё есть Error Trigger и отдельный error workflow. Не считайте, что ручной тест автоматически проверил такой сценарий: в этом материале error workflow не подключён и его срабатывание не тестировалось.
Записать ошибки workflow через Error Trigger
Не добавляйте полный $json в текст ошибки: там могут оказаться имена, документы или секреты. Даже короткое сообщение не очищает историю предыдущих узлов. Для реальной системы нужны отдельные правила доступа и сроков хранения. Исправлять проверку следует по договору данных, а не ради зелёного значка запуска.
Что проверено редакцией
15 октября 2026 года схема проверена на n8n 2.42.4 в отдельном Docker-экземпляре штатными ручными запусками API. Все 23 проверки прошли: корректный пакет, одна запись, обратный порядок, лишнее поле, пустой массив, строковая/null/отсутствующая/отрицательная/дробная/небезопасная сумма, переполнение итога, повтор/отсутствие/пустой ID, пустой клиент, null и массив вместо заказа, несколько причин, orders null/отсутствует/объект и намеренно неверный IF. Сверены точные предпросмотры, выходы IF, сообщение ошибки, последний выполненный узел и отсутствие успешного предпросмотра при нарушениях. Основные отклонения завершаются на штатном Stop And Error версии 1; неверный IF отдельно ловит проверочный Code. Официальная документация и код узла сверены. Редакторские клики, Cloud, Error Object, error workflow, автоматические триггеры, бинарные данные, большие наборы и внешние API не тестировались. Учебный контейнер остановлен, чужие workflows не менялись. Обложка — редакционная AI-иллюстрация.
Частые вопросы
Чем Stop And Error отличается от IF?
IF выбирает ветку, но сам по себе не объявляет данные ошибочными. В нашей false-ветке Stop And Error явно завершает запуск с заданным сообщением.
Почему неверный заказ останавливает весь пакет?
Так устроено правило Check Batch: сначала проверяется весь orders, затем принимается одно решение. Это не обязательное поведение всех схем n8n. Для независимой обработки заказов нужна другая схема.
Stop And Error отменяет уже выполненные действия?
Нет. Он не откатывает отправленные запросы, письма и записи в CRM. Поэтому в примере проверка стоит до любых действий, а внешних операций вообще нет.
Почему пустой массив вызывает ошибку, а ноль items может не вызвать?
Источник примера возвращает один item с orders: [], и проверка его получает. Если предыдущий узел не выдаёт ни одного item, последующие узлы могут не запуститься. Обработку такого случая нужно проектировать отдельно.
После ручного теста должен прийти Error Trigger?
В этой инструкции он не подключён. Проверка ручной ошибки не доказывает работу error workflow для автоматических запусков. Настройте и протестируйте обработчик отдельно.