hermes - 💡(How to fix) Fix Gateway service templates can persist pytest temp Node paths into systemd/launchd PATH

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…

Root Cause

This is related to service-template hygiene, not provider/API behavior. It is especially risky because the operational recovery command suggested by status (hermes gateway restart) is also the path that may refresh the unit.

Fix Action

Fix / Workaround

A local patch currently adds:

Code Example

/home/user/.local/bin/node -> /tmp/pytest-of-user/pytest-36/.../hermes_test/node/bin/node

---

ln -sfn /tmp/pytest-of-user/pytest-42/test_x/hermes_test/node/bin/node ~/.local/bin/node

---

hermes gateway status

---

/tmp/pytest-of-user/.../hermes_test/node/bin

---

def _looks_like_pytest_temp_path(path: str | Path) -> bool:
    raw = str(path)
    return "/pytest-of-" in raw or "/hermes_test/" in raw or raw.endswith("/hermes_test")


def _resolved_executable_dir_for_service(executable: str) -> str | None:
    resolved = shutil.which(executable)
    if not resolved:
        return None
    resolved_dir = Path(resolved).resolve().parent
    if _looks_like_pytest_temp_path(resolved_dir):
        return None
    return str(resolved_dir)

---

tests/hermes_cli/test_gateway_service.py::TestGeneratedSystemdUnits::test_user_unit_skips_pytest_temp_resolved_node_directory

---

3 passed
RAW_BUFFERClick to expand / collapse

Bug Description

hermes gateway status can report the installed systemd unit as outdated, and hermes gateway restart / unit refresh may persist a pytest temporary Node.js path into the gateway service PATH.

The issue happens when shutil.which("node") finds a symlink such as ~/.local/bin/node, and resolving that symlink points into a pytest temp tree, for example:

/home/user/.local/bin/node -> /tmp/pytest-of-user/pytest-36/.../hermes_test/node/bin/node

generate_systemd_unit() resolves the Node binary directory and appends the resolved parent directory into the generated service PATH. This makes the current template include a pytest tempdir. As a result:

  1. hermes gateway status reports the installed unit as outdated even when the functional service parameters are current.
  2. A refresh/restart path can bake the pytest tempdir into ~/.config/systemd/user/hermes-gateway*.service.
  3. Profile units can end up with polluted PATH entries such as /tmp/pytest-of-.../hermes_test/node/bin.

Steps to Reproduce

  1. Have a user-local node symlink resolving to a pytest tempdir:
ln -sfn /tmp/pytest-of-user/pytest-42/test_x/hermes_test/node/bin/node ~/.local/bin/node
  1. Ensure ~/.local/bin is before the real Node install on PATH.
  2. Run:
hermes gateway status

or compare the installed user unit with generate_systemd_unit(system=False).

Expected Behavior

Hermes should not persist pytest/test temp paths into generated system service definitions. If a resolved executable path looks like a test tempdir, it should be ignored for service-template PATH generation.

Actual Behavior

generate_systemd_unit() and generate_launchd_plist() append the resolved Node directory without filtering test temp paths. This can produce a service PATH containing:

/tmp/pytest-of-user/.../hermes_test/node/bin

Local Fix / Proposed Solution

Add a small guard for generated service PATH entries:

  • Detect paths containing /pytest-of-, /hermes_test/, or ending in /hermes_test.
  • When resolving node for systemd / launchd service generation, skip the resolved executable directory if it matches that detector.
  • Reuse the same detector in refresh_systemd_unit_if_needed() so user-scope unit refresh refuses to write polluted generated units.

A local patch currently adds:

def _looks_like_pytest_temp_path(path: str | Path) -> bool:
    raw = str(path)
    return "/pytest-of-" in raw or "/hermes_test/" in raw or raw.endswith("/hermes_test")


def _resolved_executable_dir_for_service(executable: str) -> str | None:
    resolved = shutil.which(executable)
    if not resolved:
        return None
    resolved_dir = Path(resolved).resolve().parent
    if _looks_like_pytest_temp_path(resolved_dir):
        return None
    return str(resolved_dir)

and uses it in both systemd and launchd generation.

Test Coverage Added Locally

A local regression test verifies that a pytest-temp resolved Node path is omitted from the generated systemd unit:

tests/hermes_cli/test_gateway_service.py::TestGeneratedSystemdUnits::test_user_unit_skips_pytest_temp_resolved_node_directory

Sanity tests run locally:

3 passed

Environment

  • OS: Linux
  • Install mode: user systemd service
  • Repo: NousResearch/hermes-agent
  • Affected area: hermes_cli/gateway.py

Notes

This is related to service-template hygiene, not provider/API behavior. It is especially risky because the operational recovery command suggested by status (hermes gateway restart) is also the path that may refresh the unit.

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 - 💡(How to fix) Fix Gateway service templates can persist pytest temp Node paths into systemd/launchd PATH