Skip to content

fix(telegram): exclude EADDRNOTAVAIL from transport fallback to avoid misleading logs and dead-code retries#95275

Closed
qingminglong wants to merge 1 commit into
openclaw:mainfrom
qingminglong:fix/94620-eaddrnotavail-telegram-fallback
Closed

fix(telegram): exclude EADDRNOTAVAIL from transport fallback to avoid misleading logs and dead-code retries#95275
qingminglong wants to merge 1 commit into
openclaw:mainfrom
qingminglong:fix/94620-eaddrnotavail-telegram-fallback

Conversation

@qingminglong

@qingminglong qingminglong commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

Summary

当系统临时端口耗尽(EADDRNOTAVAIL)时,Telegram 传输层误判为"DNS 解析的 IP 不可达",触发 fallback 切换远程 IP——这对本地 socket 分配失败毫无意义。

Root Cause

collectErrorCodes() 只收集 .code 字符串,忽略了 .errno(数值 99)。ctx.codes 为空时触发 codes.size === 0 的兜底回退。

Fix

  1. collectErrorCodes(): 增加数值 errno 提取
  2. shouldUseTelegramTransportFallback(): 遇到 EADDRNOTAVAIL(code 或 errno)时直接返回 false

Test plan

  • 45 tests passed(包括 3 个新测试)
测试 验证内容
EADDRNOTAVAIL(code) 不回退 buildFetchFallbackError("EADDRNOTAVAIL") → false
EADDRNOTAVAIL(errno) 不回退 手动构造 { errno: 99 } 的 cause → false
其他网络错误仍回退 buildFetchFallbackError("ENETUNREACH") → true

Fixes #94620

🤖 Generated with Claude Code

Real behavior proof

Behavior addressed: EADDRNOTAVAIL(临时端口耗尽)不再误触发 Telegram fallback

Real environment tested: Linux 4.19.112, Node v22.18.0

Before-fix evidence:
collectErrorCodes() 只检查 .code 字符串,EADDRNOTAVAIL 的 .code.errno 均未捕获 → ctx.codes 为空 → 触发 codes.size === 0 兜底回退,日志误导性显示 "DNS-resolved IP unreachable"。

Exact steps or command run after this patch:

npx vitest run --config test/vitest/vitest.extension-telegram.config.ts extensions/telegram/src/fetch.test.ts

After-fix evidence:
45 tests passed,新增 3 个 EADDRNOTAVAIL 测试全部通过:

✓ shouldRetryTelegramTransportFallback > returns false for EADDRNOTAVAIL code string
✓ shouldRetryTelegramTransportFallback > returns false for EADDRNOTAVAIL numeric errno
✓ shouldRetryTelegramTransportFallback > returns true for other network errors

Observed result after the fix: shouldUseTelegramTransportFallback() 在包含 "EADDRNOTAVAIL""99" 时返回 false,避免无意义 IP 切换。其他网络错误(如 ENETUNREACH)仍正常回退。

What was not tested: 未在实际 Telegram API 环境中验证(缺少 Telegram bot token)。单元测试覆盖了关键代码路径和边界条件。

EADDRNOTAVAIL 是本地 socket 分配失败,切换远程 Telegram IP 无效。
collectErrorCodes() 增加数值 errno 提取,shouldUseTelegramTransportFallback()
在 EADDRNOTAVAIL 时返回 false 避免无效回退和误导性日志。

Fixes openclaw#94620

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
@openclaw-barnacle openclaw-barnacle Bot added channel: telegram Channel integration: telegram size: XS triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. labels Jun 20, 2026
@clawsweeper

clawsweeper Bot commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed June 20, 2026, 4:24 AM ET / 08:24 UTC.

Summary
The PR adds numeric errno collection, returns false for EADDRNOTAVAIL or Linux errno 99 in Telegram transport fallback classification, and adds three classifier unit tests.

PR surface: Source +8, Tests +25. Total +33 across 2 files.

Reproducibility: yes. at source level: current main and v2026.6.8 show probeTelegram can still force-promote fallback after getMe fetch errors while the pinned-IP warning remains. I did not establish a live socket-exhaustion Telegram repro in this read-only review.

Review metrics: 1 noteworthy metric.

  • Fallback Decision Paths: 1 changed, 1 unguarded. The PR changes direct fetch classification but leaves probe forced fallback able to promote without the original error context.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #94620
Summary: This PR is a candidate fix for the canonical Telegram EADDRNOTAVAIL fallback issue, with open sibling candidate PRs and a closed unmerged prior attempt.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🧂 unranked krab
Patch quality: 🧂 unranked krab
Result: blocked until real behavior proof from a real setup is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P2] Gate probe forced fallback on the original transport error and add focused regression coverage.
  • Preserve retry behavior for non-EADDRNOTAVAIL numeric-only network failures or narrow numeric handling to EADDRNOTAVAIL.
  • [P1] Add redacted real transport, terminal, or runtime log proof after the fix; redact IP addresses, API keys, phone numbers, and non-public endpoints.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR body includes unit-test output only and explicitly says no real Telegram API or socket-exhaustion path was tested; contributor action is needed with redacted terminal, runtime log, live output, or equivalent proof, then a PR-body update should trigger re-review. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Risk before merge

  • [P2] probeTelegram can still promote Telegram fallback with a synthetic forced-fallback error after EADDRNOTAVAIL, preserving the misleading pinned-IP warning path.
  • [P2] Collecting arbitrary numeric errno values can suppress the existing code-less fetch-failed fallback for recoverable numeric-only network errors unless those errnos are mapped or EADDRNOTAVAIL is special-cased more narrowly.
  • [P1] The PR body contains copied unit-test output but no redacted runtime log, live Telegram transport proof, or OS socket-allocation proof after the fix.
  • [P1] There are overlapping open candidate PRs for the same canonical issue, so maintainers should choose one complete implementation path before landing.

Maintainer options:

  1. Complete The Fallback Boundary (recommended)
    Pass the original probe error into fallback promotion or skip forced fallback for local socket allocation failures, while preserving retry behavior for other recoverable numeric errnos.
  2. Coordinate The Candidate PRs
    Compare the open sibling fixes for the same canonical issue and keep one complete branch instead of landing overlapping partial implementations.
  3. Waive Live Proof Explicitly
    A maintainer may accept source-level proof for this rare OS condition only after the code path is complete and the proof exception is intentional.

Next step before merge

  • [P1] Human/contributor follow-up is needed because the branch has concrete code blockers, mock-only proof, and overlapping open candidates for the same canonical issue.

Security
Cleared: The diff only changes Telegram fallback classification and tests; it adds no dependency, workflow, secret, permission, install, or publishing surface.

Review findings

  • [P1] Gate probe fallback on the original transport error — extensions/telegram/src/fetch.ts:477-480
  • [P2] Preserve fallback for other numeric errnos — extensions/telegram/src/fetch.ts:431-434
Review details

Best possible solution:

Fix both the direct fetch classifier and the probe forced-fallback boundary so EADDRNOTAVAIL never promotes IP rotation while preserving valid remote/family fallback behavior, then add focused regression coverage and redacted real runtime proof or an explicit maintainer proof override.

Do we have a high-confidence way to reproduce the issue?

Yes at source level: current main and v2026.6.8 show probeTelegram can still force-promote fallback after getMe fetch errors while the pinned-IP warning remains. I did not establish a live socket-exhaustion Telegram repro in this read-only review.

Is this the best way to solve the issue?

No: the classifier guard is useful but not the best complete fix because the probe forced-fallback boundary still discards the original local socket allocation error. The safer fix carries the original error into the fallback decision and preserves valid retry behavior for other network failures.

Full review comments:

  • [P1] Gate probe fallback on the original transport error — extensions/telegram/src/fetch.ts:477-480
    The new guard only stops fallback inside the normal fetch classifier. After EADDRNOTAVAIL is thrown, probeTelegram still catches it and calls forceFallback("probe timeout/network error"), which promotes with a synthetic error and can still reach the reported pinned-IP warning. Pass the caught error into that decision or skip forced fallback for local socket allocation failures.
    Confidence: 0.92
  • [P2] Preserve fallback for other numeric errnos — extensions/telegram/src/fetch.ts:431-434
    Adding every numeric errno to ctx.codes means a TypeError("fetch failed") cause with only a numeric errno no longer satisfies the existing code-less fallback branch, while the retry set contains only string codes. Map retryable numeric errnos or special-case EADDRNOTAVAIL without turning other numeric-only network failures into fail-fast errors.
    Confidence: 0.78

Overall correctness: patch is incorrect
Overall confidence: 0.91

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 68790eb4b9a8.

Label changes

Label justifications:

  • P2: The PR targets a focused Telegram transport reliability bug with limited but real operational impact during local socket allocation failures.
  • merge-risk: 🚨 availability: Changing fallback classification affects whether Telegram retries or fails fast during network errors, and one forced-fallback path remains unsafe.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🧂 unranked krab.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body includes unit-test output only and explicitly says no real Telegram API or socket-exhaustion path was tested; contributor action is needed with redacted terminal, runtime log, live output, or equivalent proof, then a PR-body update should trigger re-review. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed

PR surface:

Source +8, Tests +25. Total +33 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 8 0 +8
Tests 1 27 2 +25
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 35 2 +33

What I checked:

  • Repository policy applied: Root AGENTS.md, extensions/AGENTS.md, and the Telegram maintainer note were read; the Telegram note requires real Telegram or equivalent live proof for transport behavior changes. (.agents/maintainer-notes/telegram.md:28, 68790eb4b9a8)
  • PR classifier change: The PR adds numeric errno values to collected codes and then blocks fallback for EADDRNOTAVAIL or numeric 99 before the existing retry decision. (extensions/telegram/src/fetch.ts:431, 3164733b7443)
  • Current fallback loop: Current main retries on known network codes or code-less TypeError('fetch failed') envelopes, so adding arbitrary numeric errnos changes the existing code-less fallback behavior. (extensions/telegram/src/fetch.ts:465, 68790eb4b9a8)
  • Probe forced fallback gap: probeTelegram catches getMe fetch errors and calls forceFallback with only a reason string, so the original EADDRNOTAVAIL classification is lost before fallback promotion. (extensions/telegram/src/probe.ts:160, 68790eb4b9a8)
  • Pinned-IP warning remains reachable: The fallback attempt chain still contains the reported DNS-resolved-IP warning, and forceFallback promotes using a synthetic Error('forced fallback') rather than the original transport error. (extensions/telegram/src/fetch.ts:566, 68790eb4b9a8)
  • Shipped behavior check: The latest release tag v2026.6.8 still has the same fallback predicate and probe forceFallback call, so the reported behavior is shipped and not only a current-main artifact. (extensions/telegram/src/probe.ts:165, 844f405ac1be)

Likely related people:

  • obviyus: Authored and merged the Telegram transport fallback unification that introduced the current fallback chain and pinned-IP warning surface. (role: feature owner; confidence: high; commits: e4825a0f9385; files: extensions/telegram/src/fetch.ts, extensions/telegram/src/fetch.test.ts)
  • scoootscooob: Moved Telegram fetch and probe implementation into extensions while preserving the fetch/probe ownership boundary now under review. (role: refactor mover; confidence: medium; commits: e5bca0832fbd; files: src/telegram/fetch.ts, src/telegram/probe.ts, extensions/telegram/src/fetch.ts)
  • Peter Steinberger: Recent git history shows repeated Telegram fetch/runtime seam work around the same module and SDK fetch boundary. (role: recent area contributor; confidence: medium; commits: a126d23f0df4, b96f5d94dba6, 55ad5d7bd769; files: extensions/telegram/src/fetch.ts, src/plugin-sdk/fetch-runtime.ts)
  • Vincent Koc: Current-main blame in this checkout points the fallback predicate and probe forceFallback lines to a recent repository snapshot, though deeper feature history is more specific. (role: recent area contributor; confidence: low; commits: 118f3f3312e4, 4251ad6638e7; files: extensions/telegram/src/fetch.ts, extensions/telegram/src/probe.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. labels Jun 20, 2026
@qingminglong

Copy link
Copy Markdown
Contributor Author

/clawsweeper

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

Labels

channel: telegram Channel integration: telegram merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. P2 Normal backlog priority with limited blast radius. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: XS status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Misleading Telegram fallback log + dead-code remote-IP retry on EADDRNOTAVAIL

2 participants