Summary
Dashboard's embedded Chat tab fails with "Chat unavailable: 1" on a plain pip/pipx install (no Docker, no git checkout). Root cause: _make_tui_argv() calls _ensure_tui_workspace(tui_dir) unconditionally before checking for a prebuilt bundle, and that function hard-exits with sys.exit(1) when ui-tui/ doesn't exist — which it never does in a pip/pipx install, since the wheel doesn't ship that directory at all (confirmed 0 matches for ui-tui in hermes_agent-0.18.0.dist-info/RECORD). The bundled fallback (hermes_cli/tui_dist/entry.js, which is shipped in the wheel and is fully valid) is never reached because the workspace check runs first and kills the process.
This looks related to #20500 and #20739, but those are Docker-image permission bugs (root-owned ui-tui/, EACCES on write). This one has no ui-tui/ directory at all, because it's a pip/pipx install rather than the Docker image or a git checkout — different trigger, same downstream symptom and same SystemExit(1) → "Chat unavailable: 1" swallow point in pty_ws.
Environment
- Hermes Agent version: v0.18.0 (2026.7.1) —
hermes version
- Install method:
pipx install hermes-agent (wheel from PyPI, not Docker, not git checkout)
- Python: 3.12.3
- OS: Ubuntu 24.04.4 LTS, kernel 6.17.0-1011-oracle, aarch64
- Node: v22.23.1 / npm 10.9.8 (both present and on
PATH — ruled out as the cause)
Steps to reproduce
- Install via pipx:
pipx install hermes-agent
- Start the dashboard:
hermes dashboard --no-open --host 0.0.0.0 --port 9119
- Open the dashboard in a browser and connect to the embedded Chat tab (
/api/pty websocket)
- Banner shows:
Chat unavailable: 1
Confirmed root cause
$ ls -la /home/ubuntu/.local/share/pipx/venvs/hermes-agent/lib/python3.12/site-packages/ui-tui
ls: cannot access '.../site-packages/ui-tui': No such file or directory
$ grep -c "ui-tui" .../hermes_agent-0.18.0.dist-info/RECORD
0
Dashboard stdout at the moment of failure:
Error: the TUI workspace is missing from this Hermes checkout.
Expected directory: /home/ubuntu/.local/share/pipx/venvs/hermes-agent/lib/python3.12/site-packages/ui-tui
This usually means `hermes update` left tracked ui-tui files deleted.
Recovery:
1. From the Hermes checkout, run `git restore -- ui-tui`
2. Run `npm install --silent --no-fund --no-audit --progress=false`
3. Retry `hermes --tui`
If the checkout is still inconsistent, run `hermes update --force`.
The recovery instructions assume a git checkout (git restore), which doesn't apply to a pip/pipx install — there's no .git here, so this guidance is a dead end for this install method.
Relevant code path in hermes_cli/main.py, _make_tui_argv():
if not ext_dir:
_ensure_tui_workspace(tui_dir) # <-- unconditional, runs BEFORE the bundled-bundle check below
# 1. Prebuilt bundle (nix / packaged release): just run it.
if not tui_dev:
if ext_dir:
...
# 1b. Bundled in wheel (pip install)
bundled = _find_bundled_tui() # <-- this succeeds; hermes_cli/tui_dist/entry.js exists and is valid
if bundled is not None:
node = _node_bin("node")
return [node, "--expose-gc", str(bundled)], bundled.parent
_ensure_tui_workspace (also in hermes_cli/main.py) is the one that hard-exits:
def _ensure_tui_workspace(tui_dir: Path) -> None:
if tui_dir.is_dir():
return
if _restore_tui_workspace(tui_dir):
...
return
print("Error: the TUI workspace is missing from this Hermes checkout. ...")
sys.exit(1)
Confirmed the bundled entry.js is present and intact and never gets a chance to run:
$ ls -la .../hermes_cli/tui_dist/entry.js
-rwxrwxr-x 1 ubuntu ubuntu 3469948 Jul 1 20:16 .../hermes_cli/tui_dist/entry.js
The SystemExit(1) propagates up to pty_ws in hermes_cli/web_server.py, which catches it and sends the unhelpful Chat unavailable: {exc} (i.e., Chat unavailable: 1) over the websocket with no further detail, so the real cause never reaches the browser or any log the end user would think to check.
Suggested fix
Reorder the checks in _make_tui_argv() so the bundled-wheel shortcut (_find_bundled_tui()) is tried before _ensure_tui_workspace() runs. The workspace check should only be a hard requirement for the git-checkout / dev-mode path, not for a packaged pip/pipx install that ships a working prebuilt bundle and has no ui-tui/ source tree by design.
As a secondary improvement (also flagged in #20739): pty_ws swallowing SystemExit into a bare Chat unavailable: {exc} hides the actual error from the user. Printing/logging the pre-sys.exit message server-side is already happening (it showed up in the dashboard's stdout in my case), but surfacing at least a pointer to "check the dashboard process's stdout/log" in the websocket message would save the next person the trial and error.
Workaround
Manually creating an empty ui-tui/ directory at the expected path makes _ensure_tui_workspace a no-op (tui_dir.is_dir() returns True) and lets execution fall through to _find_bundled_tui(), which then succeeds. Not proposing this as the fix — just confirms the diagnosis.
Summary
Dashboard's embedded Chat tab fails with "Chat unavailable: 1" on a plain
pip/pipxinstall (no Docker, no git checkout). Root cause:_make_tui_argv()calls_ensure_tui_workspace(tui_dir)unconditionally before checking for a prebuilt bundle, and that function hard-exits withsys.exit(1)whenui-tui/doesn't exist — which it never does in apip/pipxinstall, since the wheel doesn't ship that directory at all (confirmed 0 matches forui-tuiinhermes_agent-0.18.0.dist-info/RECORD). The bundled fallback (hermes_cli/tui_dist/entry.js, which is shipped in the wheel and is fully valid) is never reached because the workspace check runs first and kills the process.This looks related to #20500 and #20739, but those are Docker-image permission bugs (root-owned
ui-tui/,EACCESon write). This one has noui-tui/directory at all, because it's a pip/pipx install rather than the Docker image or a git checkout — different trigger, same downstream symptom and sameSystemExit(1)→"Chat unavailable: 1"swallow point inpty_ws.Environment
hermes versionpipx install hermes-agent(wheel from PyPI, not Docker, not git checkout)PATH— ruled out as the cause)Steps to reproduce
pipx install hermes-agenthermes dashboard --no-open --host 0.0.0.0 --port 9119/api/ptywebsocket)Chat unavailable: 1Confirmed root cause
Dashboard stdout at the moment of failure:
The recovery instructions assume a git checkout (
git restore), which doesn't apply to a pip/pipx install — there's no.githere, so this guidance is a dead end for this install method.Relevant code path in
hermes_cli/main.py,_make_tui_argv():_ensure_tui_workspace(also inhermes_cli/main.py) is the one that hard-exits:Confirmed the bundled entry.js is present and intact and never gets a chance to run:
The
SystemExit(1)propagates up topty_wsinhermes_cli/web_server.py, which catches it and sends the unhelpfulChat unavailable: {exc}(i.e.,Chat unavailable: 1) over the websocket with no further detail, so the real cause never reaches the browser or any log the end user would think to check.Suggested fix
Reorder the checks in
_make_tui_argv()so the bundled-wheel shortcut (_find_bundled_tui()) is tried before_ensure_tui_workspace()runs. The workspace check should only be a hard requirement for the git-checkout / dev-mode path, not for a packaged pip/pipx install that ships a working prebuilt bundle and has noui-tui/source tree by design.As a secondary improvement (also flagged in #20739):
pty_wsswallowingSystemExitinto a bareChat unavailable: {exc}hides the actual error from the user. Printing/logging the pre-sys.exitmessage server-side is already happening (it showed up in the dashboard's stdout in my case), but surfacing at least a pointer to "check the dashboard process's stdout/log" in the websocket message would save the next person the trial and error.Workaround
Manually creating an empty
ui-tui/directory at the expected path makes_ensure_tui_workspacea no-op (tui_dir.is_dir()returnsTrue) and lets execution fall through to_find_bundled_tui(), which then succeeds. Not proposing this as the fix — just confirms the diagnosis.