Skip to content

fix: use absolute() instead of resolve() in _remap_path_for_user to preserve venv symlinks - #8551

Closed
nurgeldy wants to merge 2 commits into
NousResearch:mainfrom
nurgeldy:fix/gateway-venv-symlink
Closed

fix: use absolute() instead of resolve() in _remap_path_for_user to preserve venv symlinks#8551
nurgeldy wants to merge 2 commits into
NousResearch:mainfrom
nurgeldy:fix/gateway-venv-symlink

Conversation

@nurgeldy

Copy link
Copy Markdown

Problem

When installing a system gateway service via sudo hermes gateway install --system, the generated ExecStart points to the bare system Python instead of the venv Python. This causes ModuleNotFoundError (e.g. No module named 'yaml') because the system Python doesn't have project dependencies installed.

Root Cause

_remap_path_for_user() in hermes_cli/gateway.py uses Path(path).resolve() which follows symlinks. The venv Python (venv/bin/python) is typically a symlink to the system Python binary. After resolve(), the symlink target replaces the venv path. Since the resolved path lives under a different prefix than the current user's home, the remap returns it as-is — losing the venv context entirely.

Flow:

  1. get_python_path() correctly detects venv/bin/python
  2. _remap_path_for_user(python_path, home_dir) calls Path(python_path).resolve()
  3. Symlink resolves to /usr/local/share/uv/python/cpython-3.11-.../bin/python3.11
  4. Resolved path is NOT under /root/, so remap returns it unchanged
  5. Service file gets the bare Python, not the venv Python

Fix

Path.absolute() converts relative paths to absolute without following symlinks. This preserves the venv Python path through the remapping logic.

-    resolved = Path(path).resolve()
+    resolved = Path(path).absolute()

Verification

After the fix, sudo hermes gateway install --system generates:

ExecStart=/home/user/.hermes/hermes-agent/venv/bin/python -m hermes_cli.main gateway run --replace

Instead of the previous broken output:

ExecStart=/home/user/.local/share/uv/python/cpython-3.11.15-linux-x86_64-gnu/bin/python3.11 -m hermes_cli.main gateway run --replace

…reserve venv symlinks

Path.resolve() follows symlinks, which converts venv Python paths
(venv/bin/python -> /uv/python/...) before the prefix remapping logic
runs. When installing a system service via sudo, this causes the
generated ExecStart to point to the bare system Python (no packages)
instead of the venv Python, resulting in ModuleNotFoundError for
dependencies like pyyaml.

Path.absolute() converts relative paths to absolute without following
symlinks, preserving the venv Python path through the remap.
…is absent

hermes status only checked systemctl --user is-active for the user
service. Servers running the system service (--system) always showed
stopped. Now checks both user and system services, reporting whichever
is active.
@teknium1

Copy link
Copy Markdown
Contributor

Already fixed on main via PR #8861 (salvage of #7735 by @akhater). The current code drops .resolve() entirely and uses .expanduser() for lexical-only expansion, preserving venv symlinks. Thanks for the contribution!

@teknium1 teknium1 closed this Apr 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants