Debugging & Troubleshooting
Checking logs
On top of Hermes' own logging pipeline, the plugin keeps an OpenClaw-style file log, written daily to:
~/.yoooclaw/plugins/yoooclaw-hermes/logs/YYYY-MM-DD.logYOOOCLAW_HERMES_LOG_DIR overrides the log directory. Stable builds redact common secrets, user text, user URLs, emails, phone numbers, bearer tokens, JWTs, and long hex tokens before writing to file or handing records to Hermes' upstream log handler; builds whose version string contains beta keep raw logs, for easier debugging (same behavior as the OpenClaw plugin). Worth noting when debugging: redaction can hide the exact value that's actually broken (e.g. a fragment of an api-key) — check whether the plugin version has beta in it if you need to see raw values. Logs older than 30 days are pruned automatically; adjust retention with YOOOCLAW_HERMES_LOG_RETENTION_DAYS.
Search logs through the Hermes plugin CLI:
hermes yoooclaw logs --keyword relay --from 2026-06-01 --to 2026-06-04 --limit 50The foreground daemon child process's stdout/stderr, managed by Hermes, is written separately to:
~/.yoooclaw/hermes-plugin/daemon-fg.logThe self-update installer log lives at <state_root>/hermes-plugin/update/update.log, with its exit code in exit_code in the same directory.
Lifecycle diagnostics
For upgrade or connection issues, start by checking lifecycle status:
hermes yoooclaw lifecycle statusLook at whether the current daemon claims owner=hermes-plugin and ingressMode=proxied, and whether the generation matches the current plugin version / profile / Relay environment / api-key. A mismatch should trigger the plugin to auto-restart the service group; if it doesn't, trigger it manually:
hermes yoooclaw lifecycle restartThe generation is a SHA-256 computed from the plugin version, embedded CLI binary hash, active profile, Relay environment, Relay URL, api-key fingerprint, ingress mode, and the local egress-callback URL. Any of those changing means the generation no longer matches, which triggers a takeover/restart.
lifecycle status's status field has three distinct meanings:
| Status | Meaning | Watchdog behavior |
|---|---|---|
mismatch | A daemon exists but owner/generation/ingressMode don't match, or the daemon has no lifecycle metadata at all (e.g. a user manually ran yc daemon start) | Triggers a takeover restart |
unknown | The daemon status probe itself failed (not "not running" — the probe couldn't get a result) | Treated as tolerable transient noise — does not restart immediately; requires YOOOCLAW_HERMES_LIFECYCLE_MISMATCH_STREAK (default 2) consecutive occurrences first |
| Daemon child exited unexpectedly | The watchdog detects its own owned process exited | Restarts the whole group immediately, bypassing the mismatch-streak threshold (distinguished from a user-initiated daemon stop via an internal _owned_process_seq counter) |
Environment & Relay checks
hermes yoooclaw env # current profile + Relay status
yoooclaw auth show # is the api-key in place (shared credentials.json with the plugin)
yoooclaw tunnel status # tunnel connection status from the underlying CLI's point of viewBecause the daemon runs inside Hermes with --ingress proxied, it never opens its own Relay tunnel — tunnel status only shows the local sidecar's view. The actual openclaw-service connection is maintained by the plugin's OpenClawRelayTransport; trust lifecycle status and the plugin logs, not the CLI-side tunnel status, for the real picture.
PHONE_NOTIFICATIONS_ENV resolution precedence: an explicit env var wins, then the active profile's relay host (if CLI version ≥ 0.2.4, it reads this var and overrides the built-in default host), then falls back to production. An unrecognized value doesn't error — it silently falls back to production. If an environment switch "doesn't seem to take," double-check the variable's spelling first.
Common error messages
These are the literal error strings (with their code) the plugin code throws — searchable keywords for logs or chat transcripts:
| Error message | code | When it happens | What to do |
|---|---|---|---|
Embedded YoooClaw CLI is not available for <os>/<arch>. | YOOOCLAW_CLI_UNSUPPORTED_PLATFORM | No embedded CLI binary for the current platform (only darwin-arm64/x64, linux-arm64/x64, win32-x64 are supported) | Confirm the platform is supported |
Embedded CLI binary is missing: <path>. | YOOOCLAW_CLI_BINARY_MISSING | The embedded binary file is missing | Reinstall the plugin |
Embedded CLI checksum mismatch: <path>. | YOOOCLAW_CLI_CHECKSUM_MISMATCH | The embedded binary was tampered with or the install is corrupted | See "CLI checksum mismatch" below |
YoooClaw CLI timed out after <n>s. | YOOOCLAW_CLI_TIMEOUT | A call to the embedded CLI subprocess timed out | Check whether the daemon is stuck, or raise the timeout |
Could not find `yc`, `yoooclaw` in PATH. | YOOOCLAW_CLI_NOT_FOUND | Neither the embedded shim nor a local-dev yc/yoooclaw is on PATH | Check whether YOOOCLAW_HERMES_INSTALL_CLI was set to 0, or whether YOOOCLAW_CLI_PATH points at a nonexistent path |
YoooClaw daemon did not become ready within <n>s | — | The daemon child didn't become ready within ready_timeout_seconds (default 25s) and was force-terminated to avoid leaking | Check daemon.lastError in hermes yoooclaw lifecycle status — usually a port conflict or host environment issue |
YoooClaw daemon did not reach the expected proxied lifecycle | — | The daemon started but never entered proxied ingress mode | Investigate via daemon logs — usually a config or port conflict |
YoooClaw openclaw-service Relay api-key is missing | — | Tried to connect to Relay with no api-key configured | yoooclaw auth set-default-api-key |
YoooClaw openclaw-service Relay authentication failed label=... : ... Update ~/.yoooclaw/credentials.json and reconnect. | — | The api-key was rejected (401/403/4401/invalid apikey) — this does not retry silently forever | Update the matching key in credentials.json; auto-reconnect alone won't fix it |
Timed out connecting to YoooClaw openclaw-service Relay | — | The handshake phase timed out | Check network connectivity |
YoooClaw Relay is disconnected / openclaw-service Relay is disconnected | — | Tried to send a frame with no connected tunnel | Wait for reconnect, or lifecycle restart manually |
No active YoooClaw APP route for chat <id> | — | The target APP session has no active connection | Confirm the APP side is online |
YoooClaw egress callback server is not running | — | The local egress-callback HTTP server was accessed before it started | Usually an internal timing issue — lifecycle restart |
YoooClaw daemon is not running / YoooClaw daemon status did not include a port | — | The daemon bridge layer couldn't find a usable daemon | First confirm the daemon's own status |
更新未执行:需要用户在对话中明确同意后,以 confirm=true 调用。 | YOOOCLAW_UPDATE_NOT_CONFIRMED | The model called the update tool without confirm=true | Confirm explicitly in the conversation, then call again |
当前插件是开发(editable/源码树)安装,拒绝自动更新;请在插件仓库里手动升级。 | YOOOCLAW_UPDATE_EDITABLE_INSTALL | The plugin is a pip install -e editable install | Upgrade manually in the source tree — don't use self-update |
已有更新正在进行(目标版本 ...),请等待其完成。 | YOOOCLAW_UPDATE_IN_PROGRESS | An update is already running | Wait for it; a pending.json older than the timeout (default 1800s) is treated as stale and a new update is allowed anyway |
目标版本号不合法:<v> | YOOOCLAW_UPDATE_BAD_VERSION | The supplied version string is malformed | Fix the version format |
当前版本 ... 已不低于目标版本 ...,无需更新。 | YOOOCLAW_UPDATE_NOT_NEWER | The target version isn't newer than the current one | No action needed |
下载安装器失败:<error> | YOOOCLAW_UPDATE_INSTALLER_FETCH_FAILED | Fetching the installer script from OSS failed | Check network connectivity, or retry later |
启动更新进程失败:<error> | YOOOCLAW_UPDATE_SPAWN_FAILED | Spawning the update subprocess failed | Check permissions and disk space |
Common symptoms → fixes
hermes plugins enable yoooclaw fails to find the plugin
Hermes 0.15.1 and earlier's plugins enable/disable/list only recognizes directory-based plugins — it doesn't scan Python entry points. Edit ~/.hermes/config.yaml directly:
plugins:
enabled: [yoooclaw, yoooclaw_app]then hermes gateway restart. The one-click installer already handles this write automatically; you only need to do it yourself after a plain pip install.
Installer aborts with "Hermes version too low"
Requires Hermes Agent >= 0.14.0, because the APP adapter depends on the PluginContext.register_platform platform API that earlier versions don't have. Upgrade Hermes first (hermes update), then re-run the installer — this is a deliberate hard check, not an installer bug.
Installer reports "could not determine the Hermes Python environment"
The installer tries a handful of standard paths to locate the venv Python that Hermes actually uses, and refuses to install if it can't find one — rather than installing into a generic Python where the gateway might fail to import the plugin later. The error lists every path it tried. Three ways to fix it: set HERMES_HOME; put Hermes' own hermes command on PATH; or explicitly pass --python /path/to/hermes-agent/venv/bin/python.
Installer reports "Python version too old"
yoooclaw-hermes-plugin requires Python ≥ 3.11. Check what Python version created the venv Hermes uses, and rebuild the venv if needed.
CLI checksum mismatch (YOOOCLAW_CLI_CHECKSUM_MISMATCH)
The embedded CLI binary's hash doesn't match what the plugin package's manifest.json records — usually a corrupted install or an accidentally modified file. The plugin first tries falling back to a previously cached install (picking the most recent by mtime); if none is available it leaves PATH untouched (commands then fail with YOOOCLAW_CLI_NOT_FOUND). A full fix requires reinstalling the plugin.
APP won't connect / sessions are unresponsive
Check in order:
yoooclaw auth show— the account-level api-key is configured and shared with the plugin's~/.yoooclaw/credentials.json;- no leftover
YOOOCLAW_APP_API_KEY/YOOOCLAW_API_KEY/YOOOCLAW_APP_ALLOWED_USERS/YOOOCLAW_APP_ALLOW_ALL_USERS/ the deprecatedYOOOCLAW_APP_RELAY_URLin the environment (the installer strips these from~/.hermes/.envon every install, but check manually if you've edited environment variables by hand); hermes yoooclaw lifecycle status— daemon owner/generation/ingressMode all line up;- check the plugin logs with
--keyword relayfor connection errors; - if you see
chat.send is only allowed for yoooclaw_app sessions, the target session doesn't belong toyoooclaw_app— the plugin deliberately fails closed on cross-channelchat.send, this isn't a bug; - in a multi-device setup, all connections sharing the same api-key receive the same broadcast, and each Hermes instance processes it once — if you see "the same message got answered twice," check whether multiple Hermes instances are sharing one key.
Relay websocket keeps dropping
The adapter's built-in watchdog restarts the whole service group once disconnection exceeds YOOOCLAW_HERMES_WS_RESTART_AFTER (default 30s — a brief network blip won't trigger a full restart), retrying failed recoveries with exponential backoff capped at YOOOCLAW_HERMES_LIFECYCLE_MAX_BACKOFF (default 60s). Egress events generated while disconnected (e.g. recording.status) are buffered (cap 100, TTL 60s, stale ones dropped) and replayed in order on reconnect — recent events aren't lost. If reconnection keeps failing, it's usually a network issue or an expired api-key (401/403/4401/invalid apikey all fail fast rather than retrying silently forever), not a problem with the watchdog itself — confirm the key hasn't expired with yoooclaw auth show first.
If the remote reconnect keeps failing but the local daemon is healthy, the watchdog recovers the local daemon independently and keeps retrying the remote connection — you won't end up stuck with "WS down and the daemon also stopped."
Behavior didn't change after upgrading / skills didn't update
~/.hermes/skills/yoooclaw/ is copied in at install time (not symlinked, because Hermes doesn't trust site-packages paths), marked with a .yoooclaw-managed file. If that directory already exists but wasn't created by the plugin (no marker present), the plugin logs a warning and skips overwriting it rather than forcing a replace. If skills didn't update after an upgrade, check whether that directory was manually modified.
Update seems stuck / no notification after it finishes
Self-update is asynchronous: a watcher thread in the old process streams update.log to the last-known APP chat session until the exit_code file appears or the timeout (default 1800s, treated as exit code 124 on timeout) is reached. hermes gateway restart is triggered by the installer script itself; the reloaded plugin process then calls resume_after_reload(), which atomically renames pending.json → pending.claimed.json so the old and new process paths can't both send a notification. If nothing seems to be happening, check <state_root>/hermes-plugin/update/update.log and the exit_code file in the same directory for the actual status.
Uninstalling the plugin
There's no dedicated uninstall script in the repo. To uninstall, run pip uninstall yoooclaw-hermes-plugin, then manually remove yoooclaw and yoooclaw_app from plugins.enabled in ~/.hermes/config.yaml, then restart the gateway.
Next steps
- Usage & Lifecycle — environment switching, lifecycle management details.
- Standalone CLI Debugging — the underlying daemon/Relay implementation is shared, so much of the troubleshooting carries over.