Skip to content

fix(telegram): persist sticky IPv4 fallback across polling restarts (fixes #48177)#48282

Merged
obviyus merged 5 commits intoopenclaw:mainfrom
yassinebkr:fix/issue-48177-sticky-ipv4-fallback
Mar 17, 2026
Merged

fix(telegram): persist sticky IPv4 fallback across polling restarts (fixes #48177)#48282
obviyus merged 5 commits intoopenclaw:mainfrom
yassinebkr:fix/issue-48177-sticky-ipv4-fallback

Conversation

@yassinebkr
Copy link
Copy Markdown
Contributor

Summary

Hoists resolveTelegramTransport() out of createTelegramBot() so the transport and its sticky IPv4 fallback state persists across polling restarts.

Problem

When Node 22+ autoSelectFamily=true and the host has unstable IPv6 to api.telegram.org, the transport correctly enables sticky IPv4 fallback. But this state is lost on every polling restart because createTelegramBot() creates a fresh transport each time, resetting stickyIpv4FallbackEnabled = false.

This causes a repeating cycle of IPv6 timeouts — the reporter observed 47 polling stalls in 20 hours with 30s-2min message loss per stall.

Changes

  • bot.ts: Accept optional telegramTransport in TelegramBotOptions, use it if provided
  • monitor.ts: Resolve transport once before polling session creation
  • polling-session.ts: Pass transport through to bot creation

Testing

Minimal diff (+15 lines). All changes are additive — existing code paths without a pre-resolved transport still work identically.

AI-assisted (Claude Sonnet 4).

Fixes #48177

@openclaw-barnacle openclaw-barnacle bot added channel: telegram Channel integration: telegram size: XS labels Mar 16, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 16, 2026

Greptile Summary

This PR fixes a regression where the sticky IPv4 fallback state inside TelegramTransport was silently reset on every polling restart, causing repeated IPv6 connection timeouts. The fix is correct: resolveTelegramTransport() is hoisted to monitor.ts so the transport (and its internal stickyIpv4FallbackEnabled + stickyIpv4Dispatcher closure state) survives across the restart loop in TelegramPollingSession. All existing code paths without a pre-resolved transport are unaffected.

  • The change is minimal, additive, and accurately targets the root cause.
  • One minor issue: resolveTelegramTransport is imported in polling-session.ts but never called there — only TelegramTransport (the type) is used. This is dead code that should be trimmed.
  • No concerns about shared dispatcher state or race conditions; undici agents are designed for reuse, and JavaScript's single-threaded model means the stickyIpv4FallbackEnabled flag is safely mutated within the async fetch closure.

Confidence Score: 5/5

  • Safe to merge — the fix is minimal, additive, and correctly targets the root cause with no behaviour change on existing code paths.
  • The change is a small, well-scoped fix that only affects the transport wiring path. All existing callers that don't supply a telegramTransport continue to work exactly as before. The one unused import is a trivial cleanup item, not a blocker.
  • No files require special attention beyond the minor unused-import cleanup in polling-session.ts.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: extensions/telegram/src/polling-session.ts
Line: 7

Comment:
**Unused import of `resolveTelegramTransport`**

`resolveTelegramTransport` is imported here but never called anywhere in `polling-session.ts`. Only the `TelegramTransport` type is actually used. The transport is now resolved once upstream in `monitor.ts` and passed in via `opts.telegramTransport` — this file no longer needs the function itself.

```suggestion
import { type TelegramTransport } from "./fetch.js";
```

How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: 8e9c769

@obviyus obviyus self-assigned this Mar 17, 2026
yassinebkr and others added 5 commits March 17, 2026 21:52
…ixes openclaw#48177)

Hoist resolveTelegramTransport() out of createTelegramBot() so the
transport (and its sticky IPv4 fallback state) persists across polling
restarts. Previously, each polling restart created a new transport with
stickyIpv4FallbackEnabled=false, causing repeated IPv6 timeouts on
hosts with unstable IPv6 connectivity.

Changes:
- bot.ts: accept optional telegramTransport in TelegramBotOptions
- monitor.ts: resolve transport once before polling loop
- polling-session.ts: pass transport through to bot creation

AI-assisted (Claude Sonnet 4). Tested: tsc --noEmit clean.
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
@obviyus obviyus force-pushed the fix/issue-48177-sticky-ipv4-fallback branch from e6d86a4 to a5a8711 Compare March 17, 2026 16:25
@obviyus obviyus merged commit 8139f83 into openclaw:main Mar 17, 2026
8 checks passed
@obviyus
Copy link
Copy Markdown
Contributor

obviyus commented Mar 17, 2026

Landed on main.

Thanks @yassinebkr.

@yassinebkr yassinebkr deleted the fix/issue-48177-sticky-ipv4-fallback branch March 17, 2026 16:49
nikolaisid pushed a commit to nikolaisid/openclaw that referenced this pull request Mar 18, 2026
…ixes openclaw#48177) (openclaw#48282)

* fix(telegram): persist sticky IPv4 fallback across polling restarts (fixes openclaw#48177)

Hoist resolveTelegramTransport() out of createTelegramBot() so the
transport (and its sticky IPv4 fallback state) persists across polling
restarts. Previously, each polling restart created a new transport with
stickyIpv4FallbackEnabled=false, causing repeated IPv6 timeouts on
hosts with unstable IPv6 connectivity.

Changes:
- bot.ts: accept optional telegramTransport in TelegramBotOptions
- monitor.ts: resolve transport once before polling loop
- polling-session.ts: pass transport through to bot creation

AI-assisted (Claude Sonnet 4). Tested: tsc --noEmit clean.

* Update extensions/telegram/src/polling-session.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* style: fix oxfmt formatting in bot.ts

* test: cover telegram transport reuse across restarts

* fix: preserve telegram sticky IPv4 fallback across polling restarts (openclaw#48282) (thanks @yassinebkr)

---------

Co-authored-by: Yassine <[email protected]>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Ayaan Zaidi <[email protected]>
analysoor-assistant pushed a commit to analysoor-assistant/openclaw that referenced this pull request Mar 19, 2026
…ixes openclaw#48177) (openclaw#48282)

* fix(telegram): persist sticky IPv4 fallback across polling restarts (fixes openclaw#48177)

Hoist resolveTelegramTransport() out of createTelegramBot() so the
transport (and its sticky IPv4 fallback state) persists across polling
restarts. Previously, each polling restart created a new transport with
stickyIpv4FallbackEnabled=false, causing repeated IPv6 timeouts on
hosts with unstable IPv6 connectivity.

Changes:
- bot.ts: accept optional telegramTransport in TelegramBotOptions
- monitor.ts: resolve transport once before polling loop
- polling-session.ts: pass transport through to bot creation

AI-assisted (Claude Sonnet 4). Tested: tsc --noEmit clean.

* Update extensions/telegram/src/polling-session.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* style: fix oxfmt formatting in bot.ts

* test: cover telegram transport reuse across restarts

* fix: preserve telegram sticky IPv4 fallback across polling restarts (openclaw#48282) (thanks @yassinebkr)

---------

Co-authored-by: Yassine <[email protected]>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Ayaan Zaidi <[email protected]>
(cherry picked from commit 8139f83)
brandontyler pushed a commit to brandontyler/clawdbot that referenced this pull request Mar 19, 2026
…ixes openclaw#48177) (openclaw#48282)

* fix(telegram): persist sticky IPv4 fallback across polling restarts (fixes openclaw#48177)

Hoist resolveTelegramTransport() out of createTelegramBot() so the
transport (and its sticky IPv4 fallback state) persists across polling
restarts. Previously, each polling restart created a new transport with
stickyIpv4FallbackEnabled=false, causing repeated IPv6 timeouts on
hosts with unstable IPv6 connectivity.

Changes:
- bot.ts: accept optional telegramTransport in TelegramBotOptions
- monitor.ts: resolve transport once before polling loop
- polling-session.ts: pass transport through to bot creation

AI-assisted (Claude Sonnet 4). Tested: tsc --noEmit clean.

* Update extensions/telegram/src/polling-session.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* style: fix oxfmt formatting in bot.ts

* test: cover telegram transport reuse across restarts

* fix: preserve telegram sticky IPv4 fallback across polling restarts (openclaw#48282) (thanks @yassinebkr)

---------

Co-authored-by: Yassine <[email protected]>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Ayaan Zaidi <[email protected]>
pholpaphankorn pushed a commit to pholpaphankorn/openclaw that referenced this pull request Mar 22, 2026
…ixes openclaw#48177) (openclaw#48282)

* fix(telegram): persist sticky IPv4 fallback across polling restarts (fixes openclaw#48177)

Hoist resolveTelegramTransport() out of createTelegramBot() so the
transport (and its sticky IPv4 fallback state) persists across polling
restarts. Previously, each polling restart created a new transport with
stickyIpv4FallbackEnabled=false, causing repeated IPv6 timeouts on
hosts with unstable IPv6 connectivity.

Changes:
- bot.ts: accept optional telegramTransport in TelegramBotOptions
- monitor.ts: resolve transport once before polling loop
- polling-session.ts: pass transport through to bot creation

AI-assisted (Claude Sonnet 4). Tested: tsc --noEmit clean.

* Update extensions/telegram/src/polling-session.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* style: fix oxfmt formatting in bot.ts

* test: cover telegram transport reuse across restarts

* fix: preserve telegram sticky IPv4 fallback across polling restarts (openclaw#48282) (thanks @yassinebkr)

---------

Co-authored-by: Yassine <[email protected]>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Ayaan Zaidi <[email protected]>
alexey-pelykh pushed a commit to remoteclaw/remoteclaw that referenced this pull request Mar 23, 2026
…ixes openclaw#48177) (openclaw#48282)

* fix(telegram): persist sticky IPv4 fallback across polling restarts (fixes openclaw#48177)

Hoist resolveTelegramTransport() out of createTelegramBot() so the
transport (and its sticky IPv4 fallback state) persists across polling
restarts. Previously, each polling restart created a new transport with
stickyIpv4FallbackEnabled=false, causing repeated IPv6 timeouts on
hosts with unstable IPv6 connectivity.

Changes:
- bot.ts: accept optional telegramTransport in TelegramBotOptions
- monitor.ts: resolve transport once before polling loop
- polling-session.ts: pass transport through to bot creation

AI-assisted (Claude Sonnet 4). Tested: tsc --noEmit clean.

* Update extensions/telegram/src/polling-session.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* style: fix oxfmt formatting in bot.ts

* test: cover telegram transport reuse across restarts

* fix: preserve telegram sticky IPv4 fallback across polling restarts (openclaw#48282) (thanks @yassinebkr)

---------

Co-authored-by: Yassine <[email protected]>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Ayaan Zaidi <[email protected]>
(cherry picked from commit 8139f83)
alexey-pelykh pushed a commit to remoteclaw/remoteclaw that referenced this pull request Mar 23, 2026
…ixes openclaw#48177) (openclaw#48282)

* fix(telegram): persist sticky IPv4 fallback across polling restarts (fixes openclaw#48177)

Hoist resolveTelegramTransport() out of createTelegramBot() so the
transport (and its sticky IPv4 fallback state) persists across polling
restarts. Previously, each polling restart created a new transport with
stickyIpv4FallbackEnabled=false, causing repeated IPv6 timeouts on
hosts with unstable IPv6 connectivity.

Changes:
- bot.ts: accept optional telegramTransport in TelegramBotOptions
- monitor.ts: resolve transport once before polling loop
- polling-session.ts: pass transport through to bot creation

AI-assisted (Claude Sonnet 4). Tested: tsc --noEmit clean.

* Update extensions/telegram/src/polling-session.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* style: fix oxfmt formatting in bot.ts

* test: cover telegram transport reuse across restarts

* fix: preserve telegram sticky IPv4 fallback across polling restarts (openclaw#48282) (thanks @yassinebkr)

---------

Co-authored-by: Yassine <[email protected]>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Ayaan Zaidi <[email protected]>
(cherry picked from commit 8139f83)
alexey-pelykh pushed a commit to remoteclaw/remoteclaw that referenced this pull request Mar 28, 2026
…ixes openclaw#48177) (openclaw#48282)

* fix(telegram): persist sticky IPv4 fallback across polling restarts (fixes openclaw#48177)

Hoist resolveTelegramTransport() out of createTelegramBot() so the
transport (and its sticky IPv4 fallback state) persists across polling
restarts. Previously, each polling restart created a new transport with
stickyIpv4FallbackEnabled=false, causing repeated IPv6 timeouts on
hosts with unstable IPv6 connectivity.

Changes:
- bot.ts: accept optional telegramTransport in TelegramBotOptions
- monitor.ts: resolve transport once before polling loop
- polling-session.ts: pass transport through to bot creation

AI-assisted (Claude Sonnet 4). Tested: tsc --noEmit clean.

* Update extensions/telegram/src/polling-session.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* style: fix oxfmt formatting in bot.ts

* test: cover telegram transport reuse across restarts

* fix: preserve telegram sticky IPv4 fallback across polling restarts (openclaw#48282) (thanks @yassinebkr)

---------

Co-authored-by: Yassine <[email protected]>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Ayaan Zaidi <[email protected]>
(cherry picked from commit 8139f83)

# Conflicts:
#	CHANGELOG.md
alexey-pelykh pushed a commit to remoteclaw/remoteclaw that referenced this pull request Mar 28, 2026
…ixes openclaw#48177) (openclaw#48282)

* fix(telegram): persist sticky IPv4 fallback across polling restarts (fixes openclaw#48177)

Hoist resolveTelegramTransport() out of createTelegramBot() so the
transport (and its sticky IPv4 fallback state) persists across polling
restarts. Previously, each polling restart created a new transport with
stickyIpv4FallbackEnabled=false, causing repeated IPv6 timeouts on
hosts with unstable IPv6 connectivity.

Changes:
- bot.ts: accept optional telegramTransport in TelegramBotOptions
- monitor.ts: resolve transport once before polling loop
- polling-session.ts: pass transport through to bot creation

AI-assisted (Claude Sonnet 4). Tested: tsc --noEmit clean.

* Update extensions/telegram/src/polling-session.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* style: fix oxfmt formatting in bot.ts

* test: cover telegram transport reuse across restarts

* fix: preserve telegram sticky IPv4 fallback across polling restarts (openclaw#48282) (thanks @yassinebkr)

---------

Co-authored-by: Yassine <[email protected]>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Ayaan Zaidi <[email protected]>
(cherry picked from commit 8139f83)
ralyodio pushed a commit to ralyodio/openclaw that referenced this pull request Apr 3, 2026
…ixes openclaw#48177) (openclaw#48282)

* fix(telegram): persist sticky IPv4 fallback across polling restarts (fixes openclaw#48177)

Hoist resolveTelegramTransport() out of createTelegramBot() so the
transport (and its sticky IPv4 fallback state) persists across polling
restarts. Previously, each polling restart created a new transport with
stickyIpv4FallbackEnabled=false, causing repeated IPv6 timeouts on
hosts with unstable IPv6 connectivity.

Changes:
- bot.ts: accept optional telegramTransport in TelegramBotOptions
- monitor.ts: resolve transport once before polling loop
- polling-session.ts: pass transport through to bot creation

AI-assisted (Claude Sonnet 4). Tested: tsc --noEmit clean.

* Update extensions/telegram/src/polling-session.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* style: fix oxfmt formatting in bot.ts

* test: cover telegram transport reuse across restarts

* fix: preserve telegram sticky IPv4 fallback across polling restarts (openclaw#48282) (thanks @yassinebkr)

---------

Co-authored-by: Yassine <[email protected]>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Ayaan Zaidi <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: telegram Channel integration: telegram size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Sticky IPv4 fallback resets on polling restart, causing repeated IPv6 timeouts

2 participants