fix(gateway): keep Matrix password-auth in the reconnect retry queue

_platform_has_bot_credential() decides whether a failed platform may be
retried. It only inspected PlatformConfig.token / .api_key, but Matrix
supports password login (MATRIX_USER_ID + MATRIX_PASSWORD, no
MATRIX_ACCESS_TOKEN), and build_config() puts those on extra{} rather
than .token.

So a password-auth Matrix config read as credential-less, and the
reconnect watcher deleted it from the retry queue on the first transient
failure. A momentary DNS failure at boot therefore took Matrix down
permanently: the homeserver was healthy, but nothing ever retried and
recovery required a manual gateway restart. Observed live as a ~13h
outage after a boot-time "Temporary failure in name resolution".

Mirror the adapter's own gate (homeserver + user_id + password).

Read ONLY from extra, never os.getenv: build_config() already copies all
three env vars onto extra, and importing this module loads ~/.hermes/.env,
so an env fallback would report "has credential" for every Matrix config
on the host -- including the empty-primary multiplex case (#64674) that
this check exists to evict.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
e2e
2026-08-28 08:59:06 -05:00
committed by Teknium
parent f298911467
commit ea34aadfe0
+21 -1
View File
@@ -2624,7 +2624,7 @@ def _platform_has_bot_credential(platform: "Platform", platform_config: "Platfor
Platforms that do not use ``PlatformConfig.token`` always return True so we
never skip them here (Signal session paths, port-binding HTTP adapters, etc.).
"""
from gateway.config import PLATFORM_TOKEN_ENV_NAMES
from gateway.config import PLATFORM_TOKEN_ENV_NAMES, Platform
if platform not in PLATFORM_TOKEN_ENV_NAMES:
return True
@@ -2635,6 +2635,26 @@ def _platform_has_bot_credential(platform: "Platform", platform_config: "Platfor
api_key = getattr(platform_config, "api_key", None) or ""
if isinstance(api_key, str) and api_key.strip():
return True
# Matrix also authenticates by password login (MATRIX_USER_ID +
# MATRIX_PASSWORD, no MATRIX_ACCESS_TOKEN). Those credentials land in
# ``extra`` rather than ``.token``, so a token-only check reads a
# perfectly reconnectable password-auth config as credential-less and
# evicts it from the retry queue on the first transient failure — after
# which it stays down until the gateway is restarted by hand. Mirror the
# adapter's own gate: homeserver + user_id + password.
#
# Read ONLY from extra, never os.getenv: build_config() already copies all
# three env vars onto extra, and importing this module loads ~/.hermes/.env,
# so an env fallback would report "has credential" for every Matrix config
# on the box — including the empty-primary multiplex case (#64674) this
# check exists to evict.
if platform is Platform.MATRIX:
extra = getattr(platform_config, "extra", None) or {}
if all(
str(extra.get(key) or "").strip()
for key in ("homeserver", "user_id", "password")
):
return True
return False