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
Environment
Symptom
Every
hermes updaterun ends the lazy-backend refresh with: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):A feature counts as "active" if any one of its declared packages is installed.
platform.matrix,platform.slack,platform.discord,homeassistant,sms, andteamsall declare the CVE-floor pinaiohttp==3.14.1. Butaiohttpis 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 — andhermes updateproceeds 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 pullspython-olm==3.2.16, whose cffi build script compiles libolm by shelling out to make:So the falsely-activated matrix backend fails its refresh on every update, forever (the updater's "rerun
hermes updateonce 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:
Every
LAZY_DEPSentry already lists its distinctive SDK first (mautrix[...],slack-bolt,discord.py[voice], ...), with shared floor pins likeaiohttpappended after. Alternatively, exclude specs that appear in more than one feature (or in the core dependency closure) from the presence check.Separately,
platform.matrixon Windows might want asys_platform != 'win32'guard or a documented libolm prerequisite, sincepython-olmships 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: