hermes - 💡(How to fix) Fix Telegram polling can conflict without a visible duplicate gateway

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Telegram polling can get stuck in repeated 409 Conflict responses even when no second local Hermes gateway is running and no webhook is configured.

On my macOS Mac mini, the working fix was to isolate the getUpdates polling client from the normal Telegram Bot API client:

  • disable HTTP keep-alive only for the getUpdates HTTPXRequest;
  • expose HERMES_TELEGRAM_POLL_TIMEOUT and HERMES_TELEGRAM_POLL_INTERVAL knobs;
  • use short polling locally (timeout=1, poll_interval=1), while keeping normal send/edit/upload requests on the existing pooled client.

Root Cause

Telegram polling can get stuck in repeated 409 Conflict responses even when no second local Hermes gateway is running and no webhook is configured.

On my macOS Mac mini, the working fix was to isolate the getUpdates polling client from the normal Telegram Bot API client:

  • disable HTTP keep-alive only for the getUpdates HTTPXRequest;
  • expose HERMES_TELEGRAM_POLL_TIMEOUT and HERMES_TELEGRAM_POLL_INTERVAL knobs;
  • use short polling locally (timeout=1, poll_interval=1), while keeping normal send/edit/upload requests on the existing pooled client.

Fix Action

Fix / Workaround

TestResult
Hermes stopped, raw getUpdates?timeout=10 via fresh curl callsAlternating 200 / 409 Conflict behavior reproduced
Hermes stopped, raw getUpdates?timeout=1 via fresh curl callsNo conflict in short test window
PTB Application.updater.start_polling() default-style pollingConflicts reproduced
PTB direct Bot.get_updates(timeout=1) reusing same bot/clientEventually reproduced conflicts
PTB direct Bot.get_updates(timeout=1) with a fresh bot/client per poll20 polls clean
PTB Updater.start_polling(timeout=1, poll_interval=1) with keep-alive disabled for getUpdatesClean in test window
PTB Updater.start_polling(timeout=10, poll_interval=0) with keep-alive disabled for getUpdatesStill produced 409 Conflict
Patched Hermes gatewayWorking; no post-restart conflict logs observed
RAW_BUFFERClick to expand / collapse

Summary

Telegram polling can get stuck in repeated 409 Conflict responses even when no second local Hermes gateway is running and no webhook is configured.

On my macOS Mac mini, the working fix was to isolate the getUpdates polling client from the normal Telegram Bot API client:

  • disable HTTP keep-alive only for the getUpdates HTTPXRequest;
  • expose HERMES_TELEGRAM_POLL_TIMEOUT and HERMES_TELEGRAM_POLL_INTERVAL knobs;
  • use short polling locally (timeout=1, poll_interval=1), while keeping normal send/edit/upload requests on the existing pooled client.

Environment

  • Host: macOS Mac mini
  • Service mode: stock Hermes launchd gateway service
  • Telegram library path: python-telegram-bot / HTTPXRequest
  • Mode: Telegram polling, not webhook

Symptoms

  • Telegram showed the bot as typing/writing but responses stalled.
  • Gateway logs repeatedly showed Telegram polling conflicts.
  • Hermes looked alive locally while effectively missing Telegram updates.

Things ruled out

  • No second local Hermes gateway process was visible during the broken state.
  • Telegram webhook was empty.
  • Old VM/autostart paths were disabled and no active local VM poller was found.
  • Provider/model failures were separate from the Telegram getUpdates conflicts.

Reproduction matrix

TestResult
Hermes stopped, raw getUpdates?timeout=10 via fresh curl callsAlternating 200 / 409 Conflict behavior reproduced
Hermes stopped, raw getUpdates?timeout=1 via fresh curl callsNo conflict in short test window
PTB Application.updater.start_polling() default-style pollingConflicts reproduced
PTB direct Bot.get_updates(timeout=1) reusing same bot/clientEventually reproduced conflicts
PTB direct Bot.get_updates(timeout=1) with a fresh bot/client per poll20 polls clean
PTB Updater.start_polling(timeout=1, poll_interval=1) with keep-alive disabled for getUpdatesClean in test window
PTB Updater.start_polling(timeout=10, poll_interval=0) with keep-alive disabled for getUpdatesStill produced 409 Conflict
Patched Hermes gatewayWorking; no post-restart conflict logs observed

Proposed fix

A focused fix should isolate the polling transport without changing normal Telegram Bot API requests:

  • set max_keepalive_connections=0 on the getUpdates-only HTTPXRequest;
  • add opt-in bounded polling controls:
    • HERMES_TELEGRAM_POLL_TIMEOUT, clamped to 1..60;
    • HERMES_TELEGRAM_POLL_INTERVAL, clamped to 0..60;
  • leave PTB polling timing defaults unchanged unless those env vars are explicitly set;
  • add regression coverage verifying that the normal send/edit request client remains unchanged and only the polling client disables keep-alive.

Affected installations can set HERMES_TELEGRAM_POLL_TIMEOUT=1 and HERMES_TELEGRAM_POLL_INTERVAL=1 to opt into short polling. If this failure mode proves common, short polling can be considered as a separate default-behavior change.

Related issues/PRs

Related, but I did not find one describing this exact keep-alive/short-poll transport finding:

  • #6153
  • #5109
  • #29196
  • #27317
  • #25232
  • #5729

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING