Skip to content

fix(gateway): route conflict-retry start_polling failure to reconnect ladder - #25232

Closed
liuhao1024 wants to merge 1 commit into
NousResearch:mainfrom
liuhao1024:fix/issue-25221-conflict-retry-reconnect
Closed

fix(gateway): route conflict-retry start_polling failure to reconnect ladder#25232
liuhao1024 wants to merge 1 commit into
NousResearch:mainfrom
liuhao1024:fix/issue-25221-conflict-retry-reconnect

Conversation

@liuhao1024

@liuhao1024 liuhao1024 commented May 13, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

When start_polling() raises during a conflict retry in _handle_polling_conflict, the exception was logged and swallowed. Polling stayed dead with no further error callbacks, leaving the gateway "alive but deaf" until manual restart.

Root Cause

In gateway/platforms/telegram.py, _handle_polling_conflict retries start_polling() after a 409 Conflict. If that retry call itself fails (timeout, network error), the except block logged the error and returned — without routing the failure into the existing reconnect ladder.

The _handle_polling_network_error handler already has the correct pattern: when start_polling() fails in its retry path, it self-schedules a new _handle_polling_network_error task via asyncio.ensure_future (lines 814-823). The conflict-retry path was missing this.

Related Issue

N/A

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)

Changes Made

  • See commit messages for detailed changes

How to Test

  1. Run pytest tests/ -q — all tests should pass
  2. Verify the specific scenario described above is resolved

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: macOS 26.4.1

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture and workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A

Code Intelligence

  • Analyzed: _handle_polling_conflict (callers: 2, callees: 3, flows: 0)
  • Blast radius: LOW — change is inside an exception handler on a rarely-triggered retry path
  • Related patterns: _handle_polling_network_error already uses the same asyncio.ensure_future self-scheduling pattern (lines 814-823)

Regression Coverage

New test test_conflict_retry_routes_to_reconnect_on_start_polling_failure in tests/gateway/test_telegram_network_reconnect.py:

  • Mocks start_polling to raise during conflict retry
  • Asserts that a reconnect task is scheduled in _background_tasks
  • Mirrors the existing test_reconnect_self_schedules_on_start_polling_failure which covers the network-error path

Testing

tests/gateway/test_telegram_network_reconnect.py — 16 passed
tests/gateway/test_telegram_conflict.py — 6 passed

Fixes Telegram gateway can stay alive with dead polling after conflict retry start_polling failure #25221

@alt-glitch alt-glitch added type/bug Something isn't working P1 High — major feature broken, no workaround comp/gateway Gateway runner, session dispatch, delivery platform/telegram Telegram bot adapter labels May 13, 2026
… ladder

When start_polling() raises during a conflict retry in
_handle_polling_conflict, the exception was logged and swallowed.
Polling stayed dead with no further error callbacks, leaving the
gateway alive but deaf until manual restart.

Route the failure into _handle_polling_network_error which handles
retries with exponential back-off and eventual escalation to
retryable-fatal, matching the existing behavior in the network-error
retry path.

Fixes NousResearch#25221
@teknium1

Copy link
Copy Markdown
Contributor

This looks implemented on current main by a later Telegram conflict-recovery fix.

Automated hermes-sweeper review evidence:

  • gateway/platforms/telegram.py:1089 now documents that a failed conflict-retry start_polling() must not leave polling in an ambiguous/alive-but-deaf state.
  • gateway/platforms/telegram.py:1135 catches the retry failure, logs that it is scheduling the next attempt, creates a task for _handle_polling_conflict(retry_err), and falls through to fatal after the retry budget is exhausted.
  • tests/gateway/test_telegram_conflict.py:132 covers repeated failing conflict retries escalating to telegram_polling_conflict fatal state.
  • tests/gateway/test_telegram_conflict.py:343 covers the failing retry branch and asserts _polling_error_task is created.
  • The implementation was added by f260aa6dc0fd6ecafb36964c33a39276fdd8da0a (fix(telegram): recover from post-update polling conflict without entering limbo), which is contained in release tag v2026.5.28.

This is not byte-for-byte the same as the PR's proposed route through _handle_polling_network_error, but main already fixes the reported swallowed-exception/limbo behavior with equivalent conflict-retry handling and fatal escalation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery P1 High — major feature broken, no workaround platform/telegram Telegram bot adapter sweeper:implemented-on-main Sweeper: behavior already present on current main type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants