Skip to content

lazy_deps: shared aiohttp pin marks never-enabled backends active; matrix refresh then fails on Windows (python-olm needs make) #58458

Description

@cfkleins

Environment

  • hermes-agent 0.18.0, checkout at 7203898
  • Windows 11 Home (10.0.26200), Python 3.11.15, uv 0.11.26

Symptom

Every hermes update run ends the lazy-backend refresh with:

→ Refreshing 19 active lazy backend(s)...
  ⚠ platform.matrix failed to refresh: pip install failed: ...setuptools\dist.py", line 810, in _finalize_setup_keywords

The user has never enabled the Matrix platform. None of its real packages (mautrix, aiosqlite, asyncpg, aiohttp-socks) were installed.

Root cause (two bugs compounding)

1. active_features() false-positives on shared pinned deps (tools/lazy_deps.py):

def active_features() -> list[str]:
    ...
    if any(_is_present(s) for s in specs):
        active.append(feature)

A feature counts as "active" if any one of its declared packages is installed. platform.matrix, platform.slack, platform.discord, homeassistant, sms, and teams all declare the CVE-floor pin aiohttp==3.14.1. But aiohttp is an unconditional dependency of packages present in a typical install (edge-tts, firecrawl-py, discord.py), so all of those backends read as "active" for users who never enabled them — and hermes update proceeds to install their full stacks. On this machine that silently pulled in complete Discord and Slack stacks over successive updates.

2. mautrix[encryption] cannot build on Windows. The extra pulls python-olm==3.2.16, whose cffi build script compiles libolm by shelling out to make:

File "olm_build.py", line 51, in <module>
    subprocess.run(["make", "static"], cwd="libolm", check=True)
FileNotFoundError: [WinError 2] The system cannot find the file specified

So the falsely-activated matrix backend fails its refresh on every update, forever (the updater's "rerun hermes update once the upstream issue is resolved" hint never resolves).

Suggested fix

Make activity detection use a package that identifies the feature, e.g. treat the first-listed spec as primary:

if _is_present(specs[0]):
    active.append(feature)

Every LAZY_DEPS entry already lists its distinctive SDK first (mautrix[...], slack-bolt, discord.py[voice], ...), with shared floor pins like aiohttp appended after. Alternatively, exclude specs that appear in more than one feature (or in the core dependency closure) from the presence check.

Separately, platform.matrix on Windows might want a sys_platform != 'win32' guard or a documented libolm prerequisite, since python-olm ships no Windows wheels.

Workaround

Installing the matrix pins without the extra satisfies the refresh check (extras are ignored by _is_satisfied), silencing the failure until the pin moves:

uv pip install mautrix==0.21.0 aiosqlite==0.22.1 asyncpg==0.31.0 aiohttp-socks==0.11.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — degraded but workaround existsarea/install-updateInstaller, updater, packaging, wheels, doctorcomp/cliCLI entry point, hermes_cli/, setup wizardduplicateThis issue or pull request already existsplatform/windowsNative Windows-specific behavior or breakagesweeper:risk-compatibilitySweeper risk: may break existing users, config, migrations, defaults, or upgradessweeper:risk-platform-windowsSweeper risk: may break or behave differently on native Windowstype/bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions