fix(supervisor): retry appservice login at startup — a homeserver-unreachable boot race permanently kills every bridge until manual restart #126
Labels
No labels
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
nether/nether-voicebridge#126
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Failure mode
If the host running the bridge reboots and the bridge process comes up before the homeserver is reachable (or the homeserver's front proxy briefly returns 5xx), every bridge's startup
m.login.application_servicefails:Every configured bridge plus the management bot dies within ~1s of startup and never retries — the outage lasts until an operator manually restarts the service. (Observed live 2026-07-22 after a host reboot.)
The failure mode is nasty because it's masked: the Discord puppet bots reconnect fine, so
systemctl is-activereportsactiveand the process looks healthy while zero bridging is happening in either direction.Root cause
The supervisor treats a failed startup appservice login as a terminal bridge error. That's the wrong call for a network-shaped error: a 502/timeout at boot means "homeserver not up yet", not "config is wrong". The same applies to the management bot, which exits with
management-bot appservice login.Proposed fix: login retry/backoff in the supervisor
On appservice login failure with a retryable status (5xx, connect error, timeout), retry with capped exponential backoff (e.g. 5s → 10s → 20s → ... cap 60s, indefinitely or for a generous window), keeping the bridge in a "starting" state instead of failing it. Non-retryable statuses (401/403 = bad token,
M_FORBIDDEN, 404 wrong URL) should still fail fast and loudly — those are config errors.Same treatment for the management bot's login.
Why not
After=/Wants=systemd ordering instead?Restart=on-failureband-aid also doesn't fit: the process as a whole stays up (puppets alive), so systemd never sees a failure.Acceptance
as_tokenstill fails fast with a clear error (no infinite silent retry).Fix on branch
fix/126-mgmt-login-retry(bd0ec42), awaiting review/merge.Scope note: the bridge half of this issue was already closed by #130's supervisor restart backoff (a failed startup login → BridgeOutcome::Failed → backoff restart → self-heals). The remaining single-shot was the management bot (
main.rsspawned it once; "bot that fails stays down"). The fix retries insidemgmt::run:appservice_login_asnow returns the typedAppserviceHttpError, so retryability is decided structurally (no text matching — same discipline as #130'sauth_error)login_retryability_splits_on_status_class,login_error_terminal_only_with_typed_status,startup_backoff_doubles_to_a_60s_capAcceptance mapping: HS unreachable at boot → mgmt bot self-heals when it returns (bridges already did via #130); wrong
as_token→ immediate loud failure, no silent retry. The homeserver-down acceptance leg still deserves a live staging check before release.Merged to master (
32ba33a) and released in v0.3.3. The management bot now retries network-shaped login/initial-sync failures with capped backoff (5s→60s, indefinitely) and fails fast on config errors; bridges were already covered by #130's restart backoff. Closing.