hermes - ✅(Solved) Fix Dashboard reports gateway STOPPED when active profile differs from container-boot HERMES_HOME (Docker) [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
NousResearch/hermes-agent#23457Fetched 2026-05-11 03:29:24
View on GitHub
Comments
0
Participants
1
Timeline
5
Reactions
0
Participants
Timeline (top)
labeled ×4cross-referenced ×1

When Hermes runs in Docker and the user activates a non-default profile (e.g. hermes-main) after container boot, the dashboard process reads gateway state from a different directory than the gateway itself writes to. Result: the dashboard reports gateway_running: false and shows a red "STOPPED" indicator while the gateway is actually running and serving requests on every platform.

Root Cause

Two long-running processes with different HERMES_HOME:

ProcessStarted byHERMES_HOMEReads/writes
Dashboard (child of tini PID 1)entrypoint.sh at container boot/opt/data/opt/data/gateway.{pid,lock,_state.json}
GatewayUser shell after profile activation/opt/data/profiles/hermes-main/opt/data/profiles/hermes-main/gateway.{pid,lock,_state.json}

get_running_pid() in the dashboard process looks at /opt/data/gateway.pid, finds nothing (or stale data from a pre-profile-activation run), returns null, and reports stopped.

The gateway path correctly honors active_profile via get_hermes_home(). The dashboard does not re-read active_profile after boot.

Fix Action

Fix / Workaround

Workaround (host-state band-aid)

PR fix notes

PR #23492: fix(dashboard): follow active profile gateway state

Description (problem / solution / changelog)

What does this PR do?

Fixes dashboard status lookups when Hermes is running under a non-default sticky profile in Docker or other custom HERMES_HOME layouts.

Today the dashboard process can keep reading gateway.pid, gateway_state.json, and state.db from the root Hermes home it booted with, even after users switch the active profile and start the gateway from profiles/<name>. That makes the dashboard show STOPPED and 0 active sessions while the gateway is actually running in the profile directory.

This patch makes /api/status re-read the sticky active profile on each request and inspect that profile's runtime files instead of the dashboard process's boot-time home.

Related Issue

Fixes #23457

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • Added an optional explicit-path parameter to gateway.status.read_runtime_status() so callers can inspect another profile's runtime state file without mutating HERMES_HOME
  • Added _resolve_status_home() in hermes_cli/web_server.py to follow the sticky active profile on each /api/status request
  • Updated /api/status to read gateway.pid, gateway_state.json, and state.db from the resolved active-profile home
  • Returned profile-specific hermes_home, config_path, and env_path values in the status payload
  • Added a regression test covering the Docker/profile-switch case and updated existing status tests to accept explicit-path lookup arguments

How to Test

  1. Run uv run --frozen pytest -q -o addopts='' tests/hermes_cli/test_web_server.py -k 'status and not plugin'
  2. Run uv run --frozen ruff check hermes_cli/web_server.py gateway/status.py tests/hermes_cli/test_web_server.py
  3. In a Docker/custom-home setup, boot the dashboard with root HERMES_HOME, switch to a non-default profile, start the gateway there, and confirm /api/status now reports the profile runtime instead of the boot-time root

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: macOS 15 / local uv env

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

Screenshots / Logs

  • Targeted status regression tests: 8 passed, 137 deselected
  • ruff check passed
  • Local repo-wide uv run --frozen pytest tests/ -q --ignore=tests/integration --ignore=tests/e2e --tb=short -o addopts='' still hits the same pre-existing collection errors on both this branch and a clean origin/main worktree (tomllib, acp, websockets.asyncio, StrEnum under the local Python 3.10 environment)

Changed files

  • gateway/status.py (modified, +7/-3)
  • hermes_cli/web_server.py (modified, +38/-10)
  • tests/hermes_cli/test_web_server.py (modified, +69/-12)

Code Example

ln -sf /opt/data/profiles/hermes-main/gateway.pid /opt/data/gateway.pid
ln -sf /opt/data/profiles/hermes-main/gateway.lock /opt/data/gateway.lock
ln -sf /opt/data/profiles/hermes-main/gateway_state.json /opt/data/gateway_state.json
RAW_BUFFERClick to expand / collapse

Summary

When Hermes runs in Docker and the user activates a non-default profile (e.g. hermes-main) after container boot, the dashboard process reads gateway state from a different directory than the gateway itself writes to. Result: the dashboard reports gateway_running: false and shows a red "STOPPED" indicator while the gateway is actually running and serving requests on every platform.

Environment

  • Hermes v0.12.0
  • Docker container, linux/arm64 (Oracle Cloud Ampere), Debian trixie base
  • tini as PID 1 supervising the dashboard
  • Active profile: hermes-main (non-default)

Repro

  1. Start container — entrypoint.sh launches hermes dashboard --host 0.0.0.0 --port 9119 with HERMES_HOME=/opt/data
  2. Inside container, activate a non-default profile: hermes profile switch hermes-main (or set HERMES_PROFILE=hermes-main and start a new gateway)
  3. Start gateway in a shell — it resolves HERMES_HOME=/opt/data/profiles/hermes-main because the profile is active
  4. Dashboard sidebar shows GATEWAY STATUS: STOPPED and ACTIVE SESSIONS: 0 despite the gateway being healthy and platforms (telegram/discord/api_server) all connected

Root cause

Two long-running processes with different HERMES_HOME:

ProcessStarted byHERMES_HOMEReads/writes
Dashboard (child of tini PID 1)entrypoint.sh at container boot/opt/data/opt/data/gateway.{pid,lock,_state.json}
GatewayUser shell after profile activation/opt/data/profiles/hermes-main/opt/data/profiles/hermes-main/gateway.{pid,lock,_state.json}

get_running_pid() in the dashboard process looks at /opt/data/gateway.pid, finds nothing (or stale data from a pre-profile-activation run), returns null, and reports stopped.

The gateway path correctly honors active_profile via get_hermes_home(). The dashboard does not re-read active_profile after boot.

Workaround (host-state band-aid)

Symlink the state files from where the dashboard looks to where the gateway actually writes:

ln -sf /opt/data/profiles/hermes-main/gateway.pid /opt/data/gateway.pid
ln -sf /opt/data/profiles/hermes-main/gateway.lock /opt/data/gateway.lock
ln -sf /opt/data/profiles/hermes-main/gateway_state.json /opt/data/gateway_state.json

Confirmed: dashboard immediately flips to gateway_running: true and shows correct PID + connected platforms. Symlinks persist across container restarts when /opt/data is bind-mounted. Breaks if the user later switches to a different profile — symlinks would point at stale paths.

Suggested fix

Either:

  1. Dashboard re-reads active_profile per request when resolving HERMES_HOME for state-file lookups, mirroring how the gateway resolves it. Probably the right fix.
  2. Send SIGHUP to dashboard on profile switch so it re-reads env. Lighter but introduces a coordination protocol.
  3. Update entrypoint.sh to read active_profile before launching dashboard so the dashboard inherits the correct HERMES_HOME from boot. Cleanest for Docker, but doesn't help users who switch profiles after boot.

Option 1 is most robust across CLI and Docker runtime modes.

Happy to send a PR if useful — wanted to file the issue first in case there's already a planned refactor in this area.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - ✅(Solved) Fix Dashboard reports gateway STOPPED when active profile differs from container-boot HERMES_HOME (Docker) [1 pull requests, 1 participants]