API иногда отвечает ошибкой, хотя через секунду тот же запрос уже работает. В n8n можно включить Retry On Fail: узел повторит попытку с паузой и остановится на заданном пределе. Настроим это на локальном учебном GET-запросе, посчитаем реальные обращения к серверу и разведём готовые данные, неверный JSON и окончательную ошибку по разным выходам.
Результат инструкции
Учебный API дважды вернёт HTTP 500, а на третьем запросе отдаст заказ O1 на 150000 копеек, то есть 1500 рублей. Ready Order получит одну запись со status ready. Если сервер продолжит отвечать 500 или не уложится в тайм-аут, после трёх попыток Request Failed выдаст needs_review. HTTP 200 с текстовой суммой попадёт в Invalid Payload, а не в готовые данные.
Мы только читаем вымышленный заказ. AI-модель, платный сервис и отправка клиенту не нужны. Повтор запроса здесь не создаёт заказ, платёж или сообщение. Не переносите эти настройки на такие действия без отдельной защиты от дублей.
Что понадобится
- Windows, работающий Docker Desktop и уже установленный локальный n8n.
- Для проверенного примера использован n8n 2.42.4; нужен доступ к созданию нового ручного workflow.
- PowerShell, свободный порт 18113 и отдельная папка ezgpt-retry для двух файлов. API-ключи и рабочие данные не нужны.
Установить n8n локально через Docker
Шаг 1. Проверьте Docker и порт
Создайте отдельную папку ezgpt-retry и откройте в ней PowerShell. docker version должен показать раздел Server. Команда проверки порта не должна показать слушателя. Если Docker ещё запускается, дождитесь готовности. Не останавливайте рабочие контейнеры, чтобы освободить порт.
docker version
Get-NetTCPConnection -LocalPort 18113 -State Listen -ErrorAction SilentlyContinue
Если порт занят, выберите другой внешний порт и одинаково замените его в Docker-пробросе, curl и Demo Input. Внутренний порт API 18113 оставьте прежним. Редактор n8n остаётся на своём адресе; API не заменяет его.
Шаг 2. Скачайте API и workflow
В папке упражнения выполните команды. Не сохраняйте поверх собственных одноимённых файлов. Откройте оба файла в редакторе перед запуском: API хранит только вымышленные данные и счётчики попыток в памяти; workflow не содержит credentials и оставлен неопубликованным.
curl.exe --fail --location "https://ezgpt.ru/storage/article-files/n8n-retry-mock-api.cjs" --output n8n-retry-mock-api.cjs
curl.exe --fail --location "https://ezgpt.ru/storage/article-files/n8n-retry-demo.json" --output n8n-retry-demo.json
Скачать учебный API для повторов
Скачать готовый workflow Retry On Fail
Шаг 3. Запустите локальный API
Из той же папки запустите команду ниже. Образ n8n используется как среда Node.js для маленького сервера, второй редактор не запускается. Папка подключена только для чтения, а порт опубликован на 127.0.0.1. Не открывайте этот учебный API в интернет.
docker run --rm -d --name ezgpt-retry-api -p 127.0.0.1:18113:18113 --mount "type=bind,source=$((Get-Location).Path),target=/demo,readonly" --entrypoint node n8nio/n8n:2.42.4 /demo/n8n-retry-mock-api.cjs
docker logs ezgpt-retry-api
В журнале ожидается Demo retry API listening on container port 18113. Если имя контейнера занято, выясните, кому он принадлежит; неизвестный контейнер не удаляйте. API слушает 0.0.0.0 внутри контейнера, но внешний проброс ограничен локальным адресом Windows.
Шаг 4. Проверьте пустой журнал попыток
Проверьте маршрут stats, не обращаясь пока к /order. stats показывает попытки, но сам их не увеличивает. Для нового сервера и run=first ожидается пустой массив events.
curl.exe --fail "http://127.0.0.1:18113/stats?run=first"
run - произвольная метка упражнения, а не API-ключ и не idempotency key. Сервер помнит число обращений отдельно для пары mode/run. Повторный запуск с уже использованной меткой продолжает её счётчик. Для чистого нового опыта меняйте run, например first-2; не требуется удалять данные n8n. После остановки API его память исчезает.
Шаг 5. Импортируйте отдельную схему
В новом workflow откройте меню с тремя точками → Import from File и выберите n8n-retry-demo.json. Не импортируйте поверх рабочего сценария. В схеме семь узлов, соединённых так, как показано ниже. Оставьте ручной запуск, Publish не нажимайте.
Manual Trigger → Demo Input → Fetch Order
основной выход → Valid Response
true → Ready Order
false → Invalid Payload
выход ошибки Fetch Order → Request Failed
Demo Input - Edit Fields / Manual Mapping. Поле url имеет тип String, режим Fixed и значение http://host.docker.internal:18113/order?mode=temporary&run=first. Fetch Order - HTTP Request: URL в Expression {{ $json.url }}. Docker Desktop обращается к Windows через host.docker.internal; localhost внутри контейнера означал бы сам контейнер. Для n8n непосредственно в Windows используйте 127.0.0.1. Linux и Cloud в этой инструкции не проверялись.
Шаг 6. Настройте запрос и три попытки
В Fetch Order выберите Method: GET, Authentication: None. В Options задайте Response Format: JSON, Timeout: 1000 мс; Include Response Headers and Status выключено, Never Error выключено. Наш If получает само тело заказа, а HTTP-ошибка должна оставаться ошибкой узла.
Откройте Settings. Включите Retry On Fail, установите Max Tries: 3 и Wait Between Tries (ms): 1000. Это три обращения всего: исходный запрос и максимум два повтора. В наших тестах после первых двух ответов 500 пришёл один ответ 200, а интервалы между обращениями были не меньше заданной секунды с небольшой задержкой выполнения.
Retry On Fail в официальной документации n8n
Never Error здесь нельзя включать: тогда ответ 500 может считаться обычными данными HTTP-узла и не запустит нужный повтор. Настройки 1000 мс и три попытки относятся к учебному серверу, а не ко всем внешним API.
Шаг 7. Направьте окончательную ошибку отдельно
В Settings Fetch Order выберите On Error: Continue (using error output). Его выход ошибки соединён с Request Failed, а основной выход - только с Valid Response. Не выбирайте обычный Continue: следующий узел не должен принять ошибку за заказ.
Request Failed - Edit Fields / Manual Mapping, Include Other Input Fields выключено. status: String, Fixed needs_review; reason: String, Fixed request_failed; message: String, Expression {{ $json.error?.message ?? $json.error ?? "request_failed" }}. Эти поля уже заполнены в скачиваемой схеме.
Режимы On Error в документации n8n
Обработанная ошибка может закончить весь workflow зелёным статусом, но это не успешная загрузка заказа. Проверяйте конкретный выход и status. Request Failed сохраняет сообщение только в OUTPUT выполнения: здесь нет постоянного журнала, отправки оператору или Error Trigger.
Шаг 8. Проверьте содержимое успешного ответа
Valid Response - If с одним Boolean-условием is true. В левое значение Expression вставлена проверка ниже. Преобразование типов выключено. Даже HTTP 200 не означает, что нужные поля пришли в правильном формате.
{{ typeof $json.order_id === "string" && $json.order_id.trim() !== "" && Number.isSafeInteger($json.amount_minor) && $json.amount_minor >= 0 && $json.currency === "RUB" }}
true идёт в Ready Order: order_id - String {{ $json.order_id }}, amount_minor - Number {{ $json.amount_minor }}, currency - String {{ $json.currency }}, status - String, Fixed ready. В первых трёх полях включён Expression, Include Other Input Fields выключено.
false идёт в Invalid Payload: status - String, Fixed needs_review; reason - String, Fixed invalid_payload; остальные входные поля выключены. Retry On Fail задан только на Fetch Order: неверные бизнес-поля, найденные позже в If, не запускают повтор HTTP-запроса.
Шаг 9. Выполните временную ошибку
Оставьте mode=temporary и ещё не использованную метку run=first. Нажмите Execute workflow от Manual Trigger. API ответит 500 на первые две попытки и 200 на третью. В Ready Order должна быть ровно одна запись ниже; Request Failed и Invalid Payload не выполняются.
{
"order_id": "O1",
"amount_minor": 150000,
"currency": "RUB",
"status": "ready"
}
Не ждите три записи из-за трёх попыток: они относятся к одному чтению заказа. 150000 копеек = 1500 рублей. Схема не создаёт и не оплачивает заказ; ready означает только, что учебный ответ успешно получен и проверен.
Шаг 10. Посчитайте реальные обращения
В PowerShell запросите stats для той же метки run. Должны быть три события с attempt 1, 2, 3 и response_status 500, 500, 200. Разности received_at между соседними событиями должны быть около секунды или больше. Это проверка серверного журнала, а не предположение по одному зелёному выполнению.
curl.exe --fail "http://127.0.0.1:18113/stats?run=first"
Если выбрали run=first-2, замените её и в stats. Отдельные ручные curl к /order тоже входят в счётчик и могут заранее исчерпать временные ошибки. Не смешивайте их с контрольным запуском, иначе результат будет выглядеть как успех с первой попытки.
Шаг 11. Проверьте остальные режимы
Меняйте url только в Demo Input. Адрес сервера и /order остаются прежними; в query измените mode и каждый раз задайте свежую run-метку. Запускайте всю схему, а не отдельный узел со старым входом. Проверяйте OUTPUT конечной ветки и stats для своей метки.
- mode=ok&run=ok-1: один запрос 200, одна запись ready.
- mode=limited&run=limited-1: сначала 429 с Retry-After: 1, затем 200. Два обращения, одна запись ready.
- mode=permanent&run=permanent-1: три ответа 500, один needs_review в Request Failed, готового заказа нет.
- mode=unauthorized&run=unauthorized-1: три ответа 401, затем Request Failed. Повторы не исправляют права или ключ.
- mode=slow&run=slow-1: сервер задерживает ответ на 2500 мс, тайм-аут узла 1000 мс. Три обращения, Request Failed, готового заказа нет.
- mode=invalid&run=invalid-1: один ответ 200 с текстовой суммой. Invalid Payload получает needs_review; повторов HTTP нет.
- Выключите Retry On Fail и задайте mode=temporary&run=disabled-1: после первого 500 сразу Request Failed. Затем верните переключатель и Max Tries 3.
Во время mode=slow поле response_status в stats описывает запланированный ответ сервера, а не доказательство, что n8n его дождался. Результат тайм-аута проверяйте по Request Failed. В конце восстановите mode=temporary с новой run=restored-1 и снова получите три обращения и ready.
Шаг 12. Остановите учебный API
Сохраните workflow ручным и неопубликованным. Остановите только контейнер, который создали в шаге 3. --rm удалит этот контейнер после остановки; оба скачанных файла останутся в папке. Основной n8n и его volume не трогайте.
docker stop ezgpt-retry-api
Если результат отличается
| Симптом | Причина | Что проверить |
|---|---|---|
| Сразу ready без двух ошибок | Метка run уже использована | Свежая метка и stats |
| После 500 нет повторов | Retry выключен или Never Error включён | Settings и Response |
| Четыре обращения вместо трёх | Был ручной запрос к /order | Отдельная run для опыта |
| Три ошибки 401 подряд | Повторы не исправляют доступ | Ключ и права реального API |
| 200, но не ready | JSON не прошёл проверку | Тип amount_minor и currency |
| Connection refused | Нет API или неверный адрес | Контейнер, порт, host.docker.internal |
Перед подключением рабочего API
Встроенные повторы в этом примере применяются ко всем ошибкам Fetch Order, не только к 429 или 5xx. Мы действительно получили три обращения даже при 401. Для рабочей системы отдельно разделите ошибки доступа, неверные параметры и временные сбои; постоянную ошибку лучше передать человеку, чем снова нагружать сервис.
Здесь задана постоянная пауза 1000 мс. Обработка произвольного Retry-After, экспоненциальная задержка, случайный разброс и общая очередь повторов не реализованы и не тестировались. В примере 429 возвращает Retry-After: 1, но это не проверка других значений. Паузы и число попыток выбирайте по документации своего сервиса, а не копируйте учебные числа.
Не включайте автоматические повторы для создания платежей, писем, задач или заказов без подтверждённой идемпотентности. Тайм-аут не доказывает, что действие на сервере не произошло. run у нашего API - только счётчик теста, он не защищает реальные действия от дублей. Для первого рабочего варианта используйте доступ только для чтения и безопасный, документированный GET.
Разбор HTTP-ошибок без автоматических повторов
Тест содержит один входной item. Не считайте его доказательством поведения при сотнях запросов или повторе целого узла с несколькими items. Для этого нужны отдельные испытания, лимиты и контроль того, какие записи уже обработаны.
Что проверено редакцией
11 октября 2026 года workflow выполнен через CLI n8n 2.42.4 в отдельной тестовой базе с локальным API. Восемь сценариев: успех с первой попытки, два временных 500, временный 429, постоянный 401, постоянный 500, тайм-аут, неверный JSON-контракт при 200 и выключенные повторы. Серверный журнал подтвердил точное число запросов и интервалы между ними; конечные поля, ветки и отсутствие ready при сбое проверены. API остановлен, рабочие контейнеры и существующие workflows не менялись. Редактор, Cloud, реальные credentials, произвольный Retry-After, экспоненциальные задержки, несколько входных items, POST, постоянный журнал и уведомления не проверялись. Обложка - редакционная иллюстрация.
Частые вопросы
Max Tries 3 означает три повтора после первого запроса?
Нет. В проверенном примере это три обращения всего: первый запрос и до двух повторов. Сервер записал 500, 500 и 200.
Почему Never Error мешает повторять HTTP 500?
В этом упражнении HTTP-ошибка должна завершить попытку Fetch Order ошибкой. Never Error может превратить её в обычный ответ, поэтому он выключен. Проверять бизнес-поля после 200 нужно отдельно.
Retry On Fail повторяет только временные ошибки?
Нет: наш тест повторил и постоянный 401. Переключатель не заменяет классификацию ошибок. Для реального API проверяйте доступ отдельно и не рассчитывайте, что повтор исправит ключ.
Почему workflow зелёный, но заказа ready нет?
Continue (using error output) обработал окончательную ошибку и выдал needs_review. Зелёное завершение схемы не означает успешное получение заказа: проверяйте конечную ветку и status.
Можно ли так повторять создание платежа или отправку письма?
Не без отдельной защиты от повторного действия. После тайм-аута сервер мог уже выполнить запрос. Эта инструкция проверяет только чтение вымышленного заказа через GET, не платежи и не отправки.