Bug
After a SIGUSR1 restart (e.g. via config.patch), the Telegram provider starts a new getUpdates long-poll loop without fully cancelling the old one. This causes Telegram API 409 conflicts:
[telegram] getUpdates conflict: Call to 'getUpdates' failed! (409: Conflict: terminated by other getUpdates request; make sure that only one bot instance is running); retrying in 30s.
Impact
- Messages randomly routed to the old (contextless) polling loop vs the new one
- Complete context loss — the old loop processes messages without session history
- Silent failure — no user-visible error, just bizarre responses that seem to forget the conversation
Reproduction
- Run gateway normally (single instance, launchd
KeepAlive: true)
- Apply a config change via
config.patch (triggers SIGUSR1 restart)
- Watch
gateway.err.log — 409 conflicts appear within seconds
- Multiple rapid
config.patch calls in a session make it worse
Evidence
- 1,361 conflicts logged over 2 weeks (since Feb 15)
- Confirmed single process (no duplicate PIDs, no external bots)
- Only fix is full
gateway stop && sleep 5 && gateway start — graceful restart does not resolve it
Expected behavior
SIGUSR1 handler should:
- Cancel/abort the active
getUpdates long-poll HTTP request
- Wait for cancellation to complete
- Only then start the new polling loop
Environment
- OpenClaw 2026.2.22-2
- macOS (Darwin arm64)
- Telegram channel (long-polling mode, no webhook)
Bug
After a SIGUSR1 restart (e.g. via
config.patch), the Telegram provider starts a newgetUpdateslong-poll loop without fully cancelling the old one. This causes Telegram API 409 conflicts:Impact
Reproduction
KeepAlive: true)config.patch(triggers SIGUSR1 restart)gateway.err.log— 409 conflicts appear within secondsconfig.patchcalls in a session make it worseEvidence
gateway stop && sleep 5 && gateway start— graceful restart does not resolve itExpected behavior
SIGUSR1 handler should:
getUpdateslong-poll HTTP requestEnvironment