Перейти к содержимому

Надёжность

Одна попытка плюс три ретрая по умолчанию; количество меняет --retries.

Ответ Что делает
200 с ok: true доставлено
200 с ok: false ретрай; description от Telegram сохраняется как ошибка
429 ретрай после запрошенной сервером задержки
5xx ретрай с экспоненциальным backoff
сетевой сбой, таймаут, DNS ретрай с backoff, в отчёте HTTP 0
любой другой 4xx не ретраится

4xx терминален намеренно. Отозванный токен, чат, из которого бота выгнали, или сообщение, которое Telegram не может распарсить, будут отвечать одинаково сколько угодно; ретраи лишь оттягивают момент, когда ты увидишь настоящую проблему.

1 с, 2 с, 4 с плюс до 50% джиттера.

Джиттер тут не украшение. Когда флот job’ов пишет в один чат и упирается в лимит одновременно, фиксированное расписание заставляет их всех ретраить в одну и ту же секунду и снова вызывать лимит. Разброс — это разница между «восстановились» и «раскачали».

На 429 notiflow ждёт parameters.retry_after из тела; если его нет — заголовок Retry-After; если нет и его — одну секунду. Прокси и self-hosted Bot API обычно шлют заголовок, а не поле, поэтому читаются оба.

Задержка ограничена --max-retry-after (по умолчанию 60 с). Telegram иногда просит минуты, а шаг workflow, который столько простоял, обычно хуже пропущенного уведомления.

--connect-timeout (5 с) ограничивает TCP- и TLS-хендшейк, --timeout (15 с) — весь запрос. Превышение любого считается сетевым сбоем и идёт по пути backoff.

По умолчанию неудачное уведомление выходит с 0. Результат сборки — то, на что люди реально реагируют, и затирать его из-за плохой минуты у Telegram означает ухудшить сигнал, а не улучшить.

fail_on_error: true (или --fail-on-error) переворачивает это, когда доставка действительно часть контракта: код выхода становится 1, а причина попадает в выход error.

Code Name Meaning
0 OK Message delivered, or skipped by notify_on, or fail_on_error=false
1 SEND_FAILED Telegram never accepted the message and fail_on_error=true
2 USAGE Command-line parsing failed (emitted by clap)
10 MISSING_REQUIRED_INPUT bot_token, chat_id or status is empty
11 INVALID_CHAT_ID chat_id is not an integer or @username (a comma is rejected in v2)
12 INVALID_STATUS status is not success
13 INVALID_PARSE_MODE parse_mode is not MarkdownV2
14 INVALID_NOTIFY_ON notify_on lists a value outside the status set
15 INVALID_THREAD_ID message_thread_id is not a non-negative integer
16 INVALID_EDIT_MESSAGE_ID edit_message_id is not a positive integer
17 CONFIG_ERROR Config file unreadable, malformed, or the profile does not exist
18 INVALID_ARGUMENT Argument is well-formed but unusable (bad api_base, zero timeout)
20 RESERVED v1 UNSUPPORTED_BASH — never emitted by v2
22 RESERVED v1 MISSING_DEPENDENCY — never emitted by v2
30 IO_ERROR Reading stdin or a message file failed, or an output file is not writable

Коды 10–16 унаследованы от notiflow v1 дословно, поэтому workflow, который на них ветвится, переживает апгрейд. 20 и 22 принадлежали bash-рантайму — у статического бинаря нет ни bash, который мог бы оказаться старым, ни curl, который мог бы отсутствовать, — и зарезервированы навсегда, а не переиспользованы.

Начни с выхода error или с JSON-отчёта: если Telegram назвал причину, там она дословно.

Симптом Обычная причина
401 Unauthorized неверный или отозванный токен — проверь notiflow whoami
400 Bad Request: chat not found неверный chat_id либо бота никогда не добавляли в чат
403 Forbidden бот в чате, но писать не может; для канала нужен админ
400 ... can't parse entities дословный message с разметкой — см. Parse modes
429 на каждой попытке слишком много сообщений в один чат; подними --max-retry-after или шли реже
HTTP 0 до сервера не дошли — сеть, DNS или прокси на раннере

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