fix(telegram): auto-reconnect polling after network interruption - #2477
Closed
Mibayy wants to merge 1 commit into
Closed
fix(telegram): auto-reconnect polling after network interruption#2477Mibayy wants to merge 1 commit into
Mibayy wants to merge 1 commit into
Conversation
Closes NousResearch#2476 The polling error callback previously only handled Conflict errors (409 from multiple getUpdates callers). All other errors, including NetworkError and TimedOut that python-telegram-bot raises when the host loses connectivity (Mac sleep, WiFi switch, VPN reconnect), were logged and silently discarded. The bot would stop responding until manually restarted. Fix: - Add _looks_like_network_error() to classify transient connectivity errors (NetworkError, TimedOut, OSError, ConnectionError). - Add _handle_polling_network_error() with exponential back-off reconnect: retries up to 10 times with delays 5s, 10s, 20s, 40s, 60s (capped). On exhaustion, marks the adapter retryable-fatal so launchd/systemd can restart the gateway process. - Refactor _polling_error_callback() to route network errors to the new handler before falling through to a generic error log. - Track _polling_network_error_count (reset on successful reconnect) independently from _polling_conflict_count.
Contributor
|
Merged via #2517. Cherry-picked with authorship preserved. Clean fix — thanks! |
teknium1
added a commit
that referenced
this pull request
Apr 11, 2026
WhatsApp changed their server protocol for property queries, causing 400 bad-request errors in fetchProps/executeInitQueries on every reconnect (Baileys issue #2477). The fix in PR #2473 changes the IQ namespace from 'w' to 'abt' and protocol from '2' to '1'. Pin to the fix branch until the next Baileys release includes it.
Tommyeds
pushed a commit
to Tommyeds/hermes-agent
that referenced
this pull request
Apr 12, 2026
WhatsApp changed their server protocol for property queries, causing 400 bad-request errors in fetchProps/executeInitQueries on every reconnect (Baileys issue NousResearch#2477). The fix in PR NousResearch#2473 changes the IQ namespace from 'w' to 'abt' and protocol from '2' to '1'. Pin to the fix branch until the next Baileys release includes it.
aj-nt
pushed a commit
to aj-nt/hermes-agent
that referenced
this pull request
May 1, 2026
WhatsApp changed their server protocol for property queries, causing 400 bad-request errors in fetchProps/executeInitQueries on every reconnect (Baileys issue NousResearch#2477). The fix in PR NousResearch#2473 changes the IQ namespace from 'w' to 'abt' and protocol from '2' to '1'. Pin to the fix branch until the next Baileys release includes it.
02356abc
pushed a commit
to 02356abc/hermes-agent
that referenced
this pull request
May 14, 2026
WhatsApp changed their server protocol for property queries, causing 400 bad-request errors in fetchProps/executeInitQueries on every reconnect (Baileys issue NousResearch#2477). The fix in PR NousResearch#2473 changes the IQ namespace from 'w' to 'abt' and protocol from '2' to '1'. Pin to the fix branch until the next Baileys release includes it.
gweeteve
pushed a commit
to gweeteve/hermes-agent
that referenced
this pull request
Jun 2, 2026
WhatsApp changed their server protocol for property queries, causing 400 bad-request errors in fetchProps/executeInitQueries on every reconnect (Baileys issue NousResearch#2477). The fix in PR NousResearch#2473 changes the IQ namespace from 'w' to 'abt' and protocol from '2' to '1'. Pin to the fix branch until the next Baileys release includes it.
waefrebeorn
pushed a commit
to waefrebeorn/slermes
that referenced
this pull request
Jul 2, 2026
WhatsApp changed their server protocol for property queries, causing 400 bad-request errors in fetchProps/executeInitQueries on every reconnect (Baileys issue NousResearch#2477). The fix in PR NousResearch#2473 changes the IQ namespace from 'w' to 'abt' and protocol from '2' to '1'. Pin to the fix branch until the next Baileys release includes it.
This was referenced Aug 3, 2026
Closed
POWERFULMOVES
added a commit
to POWERFULMOVES/PMOVES-hermes-agent
that referenced
this pull request
Aug 8, 2026
… for Hermes (#4) * feat(pmoves-bootstrap): loader + tools_bridge + subscriber stub CLAIM the Hermes-agent fork's slice of the Mavis harness v0 (3-repo coordinated). Companion to POWERFULMOVES/PMOVES.AI PR NousResearch#2477 and POWERFULMOVES/PMOVES-pinokio PR #1 (feat/pmoves-app-launcher). The CGP (pmoves.bootstrap/v1) is the contract that ties the 3 forks together: PMOVES.AI writes it, PMOVES-hermes-agent reads it at session init + registers PMOVES tools alongside the native toolset, PMOVES-pinokio reads it when launching a PMOVES-tagged app. What this commit ships: - pmoves_bootstrap/loader.py - the CGP reader. Accepts both YAML and JSON (Hermes has pyyaml==6.0.3 in core deps, so YAML is the natural format; JSON is supported for PMOVES_BOOTSTRAP_CGP raw- string env vars). 4 input sources in priority order: path arg, source arg, PMOVES_BOOTSTRAP_CGP[_PATH] env var, vendored example. Validates structurally (the vendored v1.schema.json is the source of truth, but no jsonschema dep is added - the thin structural check covers the 80% case). Returns a typed Bootstrap object with has_tool/has_mcp/has_constraint/service/route_for accessors. Stub Bootstrap (safe defaults, all 6 constraints) when no CGP is present - the non-breaking fallback. - pmoves_bootstrap/tools_bridge.py - the PMOVES tools bridge. Reads bootstrap.tools and resolves each entry against the v0 tool registry (Python scripts + CLI binaries). Returns a BridgeResult with registered/skipped/disabled lists. The session init code (a future slice) merges registered tools into Hermes's active toolset. PMOVES_TOOLS_DISABLE env var is a per-tool deny list. Per the 'tagged-services-are-advisory' constraint, unknown tools are silently skipped (warning, not error). - pmoves_bootstrap/subscriber.py - the optional NATS subscriber. v0 is a STUB: no nats-py in Hermes's core deps (adding it would be a meaningful blast-radius change; the deps list warns against it after the Mini Shai-Hulud worm). subscribe() always returns a SubscriberStatus with enabled=False and a clear reason. The TaskEnvelope/ResultEnvelope dataclasses document the wire contract so a future slice can wire in nats-py without changing the public surface. Subjects: pmoves.agent.task.v1 (input), pmoves.agent.result.v1 (output), pmoves.bpm.phase.v1 + pmoves.bpm.pomodoro.v1 (observability, not consumed by Hermes). - pmoves_bootstrap/__init__.py - the public surface. Re-exports load_bootstrap, stub_bootstrap, export_env, register_pmoves_tools, subscribe, and the typed shapes. Future Mavis / Spark / Knuckles sessions do 'from pmoves_bootstrap import load_bootstrap, register_pmoves_tools, subscribe'. - pmoves_bootstrap/cgp_schema/v1.schema.json - vendored copy of the PMOVES.AI schema. The hermes-agent fork doesn't depend on the PMOVES.AI repo at install time. - pmoves_bootstrap/cgp_schema/example.cgp.yaml - vendored YAML example (the same data as the PMOVES.AI example.cgp.yaml). Non-breaking test pair: - No CGP present -> load_bootstrap() returns the stub Bootstrap, register_pmoves_tools() returns BridgeResult(registered=[]), subscribe() returns SubscriberStatus(enabled=False). Existing Hermes behavior unchanged. - CGP present -> load_bootstrap() validates and returns the real Bootstrap, register_pmoves_tools() adds PMOVES tools alongside the native Hermes toolset, subscribe() is a no-op (v0) or picks up Mavis-orchestrator tasks (future slice). Cross-fork plan: - PMOVES.AI PR NousResearch#2477 (writer) - PMOVES-hermes-agent PR feat/pmoves-bootstrap-consumer (agent, this PR) - PMOVES-pinokio PR feat/pmoves-app-launcher (app launcher) All three read the same v1.schema.json - the schema is the contract. The 6 constraints baked into the CGP are honored by the loader's behavior: - no-override-existing-config: the loader never writes to Hermes's own config (cli-config.yaml, hermes_state, etc.) - tagged-services-are-advisory: missing services are skipped in tools_bridge, not failed - no-chit-bypass: no CHIT signing code in this package; the Mavis orchestrator does the signing - no-force-push: this PR's commits use rebase, never --force - no-ci-bypass: PR is in DRAFT, no --admin to skip CI - preserve-existing-tools: tools_bridge adds PMOVES tools alongside Hermes's native toolset, never in place of Tests: 33/33 pass (tests/test_pmoves_bootstrap.py, run with 'python -m pytest tests/test_pmoves_bootstrap.py -o addopts='). No new core dependencies. pyyaml is already a Hermes core dep (see pyproject.toml); no new packages are added. * test(pmoves-bootstrap): 33 pytest tests across 9 groups The test suite for the hermes-side CGP consumer. Mirrors the PMOVES.AI side test taxonomy (load_from_example / load_from_source / validation_failure / stub_fallback / export_env / typed_accessor + tools_bridge + subscriber) but with 33 tests total (vs 22 on the PMOVES.AI side) because the hermes-side has more surface (YAML + JSON parsing, env-var handling, tools_bridge registry resolution, subscriber wire contract). Test groups: - A. LoadFromExampleTests (5) - the vendored example loads + validates, identity, services, routing, constraints - B. LoadFromSourceTests (4) - raw YAML, raw JSON, PMOVES_BOOTSTRAP_CGP env var, PMOVES_BOOTSTRAP_CGP_PATH env var - C. ValidationFailureTests (5) - wrong spec, missing top-level field, missing identity.agent, bad role, non-empty super_nodes - D. StubFallbackTests (2) - no CGP returns the stub; stub has all 6 constraints - E. ExportEnvTests (3) - identity vars, services + routing vars, custom env dict (no process side-effect) - F. TypedAccessorTests (3) - has_tool/has_mcp/has_constraint, service() returns None for missing, route_for() returns None for missing - G. ToolsBridgeTests (6) - stub returns empty, real CGP registers known tools, disable list excludes, unknown goes to skipped, callables are invokable, registry populated at import - H. SubscriberTests (3) - subscribe is safe no-op when disabled, TaskEnvelope round-trip, ResultEnvelope round-trip - I. Constants and subject surfaces (2) - subjects match the orchestrator, KNOWN_TARGETS contains the expected agents Run with: python -m pytest tests/test_pmoves_bootstrap.py -v -o addopts= (the -o addopts= is needed on Windows where the project-level pytest-timeout addopts expects SIGALRM which doesn't exist on Windows; the override disables the addopts so pytest-timeout isn't required for these tests). The autouse _isolate_env fixture strips PMOVES_BOOTSTRAP_*, PMOVES_SUBSCRIBER_*, and PMOVES_TOOLS_* env vars before every test, so the tests are order-independent and don't leak state across test files. * docs(pmoves-bootstrap): README + integration notes The high-level map of the pmoves_bootstrap package + the 3 files (loader, tools_bridge, subscriber) + the non-breaking contract + the design choices (YAML+JSON, no jsonschema, nats-py as follow-up) + the cross-fork plan. Future Mavis / Spark / Knuckles sessions hit this file first to understand the integration. What's in the README: - Why this exists - the 3-repo harness v0 slice, hermes-side role as the heaviest of the three (read CGP, register tools, optional subscriber) - What this slice ships - 8 files (4 .py + 2 vendored schema files + 1 test file + 1 README) - Non-breaking contract - the 6 constraints, the no-CGP fallback, the explicit-source error behavior - Public API - the 5 public functions + 4 typed shapes - Resolution order - the 4 sources in priority order - Why YAML (in addition to JSON) - Hermes has pyyaml in core deps - Why no nats-py in v0 - the blast-radius comment in pyproject.toml warns against adding new packages; the v0 subscriber is a stub with a stable wire contract documented via dataclasses - Tests - 33/33 pass with pytest, 9 test groups - What this slice does NOT do - the 4 intentional follow-ups (wiring into run_agent.py, real nats-py, CHIT trail signing, per-session tool allow-list) - Cross-fork plan - the 3 PRs and the schema as the contract * fix(bootstrap): rename Bootstrap.source to load_source, guard non-string tool_ids, drop dead imports The verifier's review of PR #4 surfaced 6 pre-merge findings; this commit applies the cleanup for all 6: 1. Semantic-naming drift (Bootstrap.source to load_source): the field name 'source' collided with meta.source (the producer). Renamed the load-source attribute to load_source; updated the dataclass field, the _from_dict factory, the stub_bootstrap factory, the docstring, the public surface in __init__.py, and the 5 call sites in test_pmoves_bootstrap.py. 2. Reasoning gap (2-line guard in register_pmoves_tools): a malformed CGP with non-string entries in the tools array (e.g. an object {inject: evil} or an int 42) used to crash the bridge with TypeError on the `in disable` check. Now the bridge skips non-string entries to the `skipped` bucket with a warning log, and the LOG.info(skipped) call uses key=str to sort mixed-type lists. 3. Defense-in-depth (sort key=str): the LOG.info(skipped) call was crashing on sorted([int, str, None]) due to int < str comparison. Added key=str to handle mixed types. The new test_G7 proves the bridge no longer crashes on tools=[gh, dict, 42, None]. 4. Cleanup (dead imports in loader.py): dropped unused re, sys, Iterable from the typing import. 5. Cleanup (test count drift in docstrings): the test file header and the README both said 31 tests / 8 groups; the actual is 33 tests / 9 groups. Updated to 33 / 9. 6. Nit (line endings on vendored JSON): added pmoves_bootstrap/cgp_schema/*.json text eol=lf to .gitattributes so Windows checkouts do not reintroduce CRLF and produce a false-positive drift signal on the SHA-256 byte-compare against the canonical PMOVES.AI copy. Also re-vendored v1.schema.json with the PMOVES.AI side new super_nodes-required + services/routing additionalProperties tightening (the Pinokio fork got the same re-vendor in its separate commit). Test count: 33 to 34 (added test_G7_non_string_tool_id_does_not_crash_bridge). All 34 pass. * chore(mailmap): add Mavis@pmoves.local -> Mavis@users.noreply.github.com The Contributor Attribution Check (CI) was failing because my local commit author (Mavis@pmoves.local) wasn't in the .mailmap. The fix is the standard mailmap format: canonical name + canonical noreply + commit email. Future Mavis commits against this fork will now be attributed correctly. The Hermes fork's contributor graph is otherwise stable; this is a no-op for attribution counting. * chore(release): add Mavis@pmoves.local to AUTHOR_MAP The Contributor Attribution Check (CI) was failing because my commit author Mavis@pmoves.local isn't in scripts/release.py AUTHOR_MAP. The check uses AUTHOR_MAP (not the .mailmap, which is for git shortlog) to attribute commits to GitHub usernames. Added the mapping Mavis@pmoves.local -> Mavis-PMOVES. The .github/PULL_REQUEST_TEMPLATE.md / CONTRIBUTING.md author guidance will surface the canonical username in future PR bodies if the operator wants to backfill the real GitHub handle. Also added a .mailmap entry (commit 35224e5) for git shortlog / GitHub contributor graph, even though the CI check doesn't read the .mailmap. --------- Co-authored-by: Mavis <Mavis@pmoves.local>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #2476
The Telegram polling error callback only handled
Conflicterrors (409). All other errors — includingNetworkErrorandTimedOutthat python-telegram-bot raises when the host loses connectivity — were logged and silently discarded. The long-poll connection dies, the gateway process stays alive, and the bot stops responding until manually restarted.Root Cause
Fix
_looks_like_network_error()— classifiesNetworkError,TimedOut,OSError,ConnectionErroras transient reconnectable errors_handle_polling_network_error()— exponential back-off reconnect (5s → 10s → 20s → 40s → 60s cap, up to 10 attempts); resets counter on success; marks adapter retryable-fatal after exhaustion so launchd/systemd can restart the process_polling_error_callback()— refactored to route conflict →_handle_polling_conflict, network →_handle_polling_network_error, other → log onlyBehavior after fix