Skip to content

Fix #2218: fix: bug: Hermes viewer daemon always reports "occupied" on Windows (connection- - #2220

Open
Memtensor-AI wants to merge 3 commits into
MemTensor:dev-v2.0.29from
Memtensor-AI:bugfix/autodev-2218-20260805062958307
Open

Fix #2218: fix: bug: Hermes viewer daemon always reports "occupied" on Windows (connection-#2220
Memtensor-AI wants to merge 3 commits into
MemTensor:dev-v2.0.29from
Memtensor-AI:bugfix/autodev-2218-20260805062958307

Conversation

@Memtensor-AI

Copy link
Copy Markdown
Collaborator

Description

Fix #2218: Hermes viewer daemon now correctly detects a free port on non-English Windows. Root cause was _probe_json_url() in apps/memos-local-plugin/adapters/hermes/memos_provider/daemon_manager.py recognising only macOS/Linux ECONNREFUSED errno values (61, 111) and the English "connection refused" substring; Windows raises errno 10061 (WSAECONNREFUSED) with a locale-dependent message (e.g. Czech "cílový počítač je aktivně odmítl") that matched neither branch, so an unused port was permanently misclassified as "blocked" and the viewer panel at http://127.0.0.1:18800/ never launched.

Fix (2 files, +86/-1 lines): (1) daemon_manager.py::_probe_json_url() — added 10061 to the errno whitelist and added isinstance(reason, ConnectionRefusedError) as a locale-agnostic type check that is load-bearing when errno is missing. (2) tests/python/test_bridge_client.py — added ProbeJsonUrlConnectionRefusedTests (6 cases): Windows errno 10061 with English + Czech messages, bare ConnectionRefusedError, macOS errno 61 (regression), Linux errno 111 (regression), and a "must stay blocked" negative case for unrelated OSError. All three Windows-related tests were red BEFORE the fix (bug reproduced) and green after.

Verification on the pushed HEAD: python3 -m unittest tests.python.test_bridge_client.ProbeJsonUrlConnectionRefusedTests tests.python.test_bridge_client.ViewerDaemonTests tests.python.test_bridge_client.BridgeOkCacheTests → 17/17 pass. python3 -m ruff check + python3 -m ruff format --check on both changed files → all clean. Live-fire cross-platform simulation confirms all six scenarios classify correctly.

Scope: bug quick-fix in one function of one file plus its unit tests; no schema, API contract, pyproject, or public interface change. .ai-tasks/2026-08-05-2218-...md and the mirrored task.md in the specs repo document the requirement clarification, root cause, and phase progress.

Related Issue (Required): Fixes #2218

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactor (does not change functionality, e.g. code style improvements, linting)
  • Documentation update

How Has This Been Tested?

Not run; documentation-only change.

  • Unit Test
  • Test Script Or Test Steps (please provide)
  • Pipeline Automated API Test (please provide)

Checklist

  • I have performed a self-review of my own code
  • I have commented my code in hard-to-understand areas
  • I have added tests that prove my fix is effective or that my feature works
  • I have created related documentation issue/PR in MemOS-Docs (if applicable)
  • I have linked the issue to this PR (if applicable)
  • I have mentioned the person who will review this PR

@whipser030, @hijzy please review this PR.

Reviewer Checklist

…port probe

`_probe_json_url()` only recognised macOS/Linux ECONNREFUSED errno values
(61, 111) and the English "connection refused" substring, so on non-English
Windows the socket raised errno 10061 with a locale-dependent message
(e.g. Czech: "cílový počítač je aktivně odmítl") that matched neither
branch. An unused port was therefore always misclassified as "blocked",
the viewer daemon never started, and http://127.0.0.1:18800/ was
permanently unreachable on fresh non-English Windows installs.

Fix:
- Add 10061 (WSAECONNREFUSED) to the errno whitelist.
- Fall back to `isinstance(reason, ConnectionRefusedError)` — Python
  raises this type consistently across platforms regardless of errno or
  locale, and is the load-bearing signal even if errno is missing.

Add 6 pytest cases in `ProbeJsonUrlConnectionRefusedTests` covering
Windows errno 10061 (English + Czech messages), bare
`ConnectionRefusedError`, macOS errno 61, Linux errno 111, and a
"must stay blocked" negative case for unrelated OSError.

Fixes MemTensor#2218

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Memtensor-AI Memtensor-AI added ai:generated Generated or modified by AI | 由 AI 生成或修改 area:plugin OpenClaw & Hermes status:in-progress Someone or AI is working on it | 人工或 AI 正在处理 labels Aug 5, 2026
@Memtensor-AI

Memtensor-AI commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator Author

🤖 Open Code Review

Target: PR #2220
Task: a0cd4477457acc81
Base: dev-v2.0.29
Head: bugfix/autodev-2218-20260805062958307
Head SHA: faeead8ffae2d753bac7f79e8ce96e4a56d13474

OpenCodeReview: No comments generated. Looks good to me.

Generated by cloud-assistant via Open Code Review.

@Memtensor-AI

Copy link
Copy Markdown
Collaborator Author

🔧 Open Code Review requested Agent fix

Open Code Review found 1 issue(s). I have resumed the development Agent to fix them.

  • Task: a0cd4477457acc81
  • Fix attempt: 1/2
  • Finding delta: 0 repeated / 1 new / 0 likely resolved

The Agent will push a new commit to this PR branch. OCR will recheck after the commit is pushed.

Address OCR finding on PR MemTensor#2220: `_run_probe` in
`ProbeJsonUrlConnectionRefusedTests` was annotated `-> object`, which
is uninformative. The helper always patches `urlopen` with a
`side_effect=urlerror`, so `_probe_json_url` only ever reaches its
`URLError` branches, all of which return `"free"` or `"blocked"`. All
six test assertions compare the result against string literals. `-> str`
makes the intent explicit and lets type checkers catch any accidental
future change to a non-string return.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Memtensor-AI

Copy link
Copy Markdown
Collaborator Author

✅ Automated Test Results: PASSED

All tests passed (69/69 executed). memos_local_plugin/changed-repo-python: 60/60, memos_python_core/changed-repo-python: 9/9. Duration: 7s

Branch: bugfix/autodev-2218-20260805062958307

@Memtensor-AI Memtensor-AI added status:ready Ready for implementation; waiting for assignee or AI dispatch | 可进入实现,等待认领或派发 and removed status:in-progress Someone or AI is working on it | 人工或 AI 正在处理 labels Aug 5, 2026
@syzsunshine219

Copy link
Copy Markdown
Collaborator

Synced this PR with the latest dev-v2.0.29 (4 target-branch commits) via merge commit ddb1984b; the merge completed without conflicts.

I independently reproduced the original regression on the target branch: a localized OSError(10061, ...) was classified as blocked. On the updated PR head it is classified as free. I found no additional defect in the PR implementation, so no functional changes beyond the target-branch sync were needed.

Local verification on ddb1984b:

  • focused regression/viewer/cache suite: 17/17 passed
  • all local-plugin Python unittest tests: 114/114 passed
  • pytest test_bridge_client.py: 60/60 passed
  • Ruff check and format check on both changed files: passed
  • git diff --check: passed

A fresh Python Actions run was triggered: https://github.com/MemTensor/MemOS/actions/runs/31122324729. OCR/AutoTest statuses have not appeared yet. GitHub currently reports a major Actions outage, so this run may remain queued until the platform recovers.

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

Labels

ai:generated Generated or modified by AI | 由 AI 生成或修改 area:plugin OpenClaw & Hermes status:ready Ready for implementation; waiting for assignee or AI dispatch | 可进入实现,等待认领或派发

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants