Skip to content

Debugging & Troubleshooting

Checking logs

On top of Hermes' own logging pipeline, the plugin keeps an OpenClaw-style file log, written daily to:

text
~/.yoooclaw/plugins/yoooclaw-hermes/logs/YYYY-MM-DD.log

YOOOCLAW_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:

bash
hermes yoooclaw logs --keyword relay --from 2026-06-01 --to 2026-06-04 --limit 50

The foreground daemon child process's stdout/stderr, managed by Hermes, is written separately to:

text
~/.yoooclaw/hermes-plugin/daemon-fg.log

The 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:

bash
hermes yoooclaw lifecycle status

Look 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:

bash
hermes yoooclaw lifecycle restart

The 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:

StatusMeaningWatchdog behavior
mismatchA 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
unknownThe 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 unexpectedlyThe watchdog detects its own owned process exitedRestarts 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

bash
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 view

Because 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 messagecodeWhen it happensWhat to do
Embedded YoooClaw CLI is not available for <os>/<arch>.YOOOCLAW_CLI_UNSUPPORTED_PLATFORMNo 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_MISSINGThe embedded binary file is missingReinstall the plugin
Embedded CLI checksum mismatch: <path>.YOOOCLAW_CLI_CHECKSUM_MISMATCHThe embedded binary was tampered with or the install is corruptedSee "CLI checksum mismatch" below
YoooClaw CLI timed out after <n>s.YOOOCLAW_CLI_TIMEOUTA call to the embedded CLI subprocess timed outCheck whether the daemon is stuck, or raise the timeout
Could not find `yc`, `yoooclaw` in PATH.YOOOCLAW_CLI_NOT_FOUNDNeither the embedded shim nor a local-dev yc/yoooclaw is on PATHCheck 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>sThe daemon child didn't become ready within ready_timeout_seconds (default 25s) and was force-terminated to avoid leakingCheck daemon.lastError in hermes yoooclaw lifecycle status — usually a port conflict or host environment issue
YoooClaw daemon did not reach the expected proxied lifecycleThe daemon started but never entered proxied ingress modeInvestigate via daemon logs — usually a config or port conflict
YoooClaw openclaw-service Relay api-key is missingTried to connect to Relay with no api-key configuredyoooclaw 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 foreverUpdate the matching key in credentials.json; auto-reconnect alone won't fix it
Timed out connecting to YoooClaw openclaw-service RelayThe handshake phase timed outCheck network connectivity
YoooClaw Relay is disconnected / openclaw-service Relay is disconnectedTried to send a frame with no connected tunnelWait for reconnect, or lifecycle restart manually
No active YoooClaw APP route for chat <id>The target APP session has no active connectionConfirm the APP side is online
YoooClaw egress callback server is not runningThe local egress-callback HTTP server was accessed before it startedUsually an internal timing issue — lifecycle restart
YoooClaw daemon is not running / YoooClaw daemon status did not include a portThe daemon bridge layer couldn't find a usable daemonFirst confirm the daemon's own status
更新未执行:需要用户在对话中明确同意后,以 confirm=true 调用。YOOOCLAW_UPDATE_NOT_CONFIRMEDThe model called the update tool without confirm=trueConfirm explicitly in the conversation, then call again
当前插件是开发(editable/源码树)安装,拒绝自动更新;请在插件仓库里手动升级。YOOOCLAW_UPDATE_EDITABLE_INSTALLThe plugin is a pip install -e editable installUpgrade manually in the source tree — don't use self-update
已有更新正在进行(目标版本 ...),请等待其完成。YOOOCLAW_UPDATE_IN_PROGRESSAn update is already runningWait 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_VERSIONThe supplied version string is malformedFix the version format
当前版本 ... 已不低于目标版本 ...,无需更新。YOOOCLAW_UPDATE_NOT_NEWERThe target version isn't newer than the current oneNo action needed
下载安装器失败:<error>YOOOCLAW_UPDATE_INSTALLER_FETCH_FAILEDFetching the installer script from OSS failedCheck network connectivity, or retry later
启动更新进程失败:<error>YOOOCLAW_UPDATE_SPAWN_FAILEDSpawning the update subprocess failedCheck 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:

yaml
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:

  1. yoooclaw auth show — the account-level api-key is configured and shared with the plugin's ~/.yoooclaw/credentials.json;
  2. no leftover YOOOCLAW_APP_API_KEY / YOOOCLAW_API_KEY / YOOOCLAW_APP_ALLOWED_USERS / YOOOCLAW_APP_ALLOW_ALL_USERS / the deprecated YOOOCLAW_APP_RELAY_URL in the environment (the installer strips these from ~/.hermes/.env on every install, but check manually if you've edited environment variables by hand);
  3. hermes yoooclaw lifecycle status — daemon owner/generation/ingressMode all line up;
  4. check the plugin logs with --keyword relay for connection errors;
  5. if you see chat.send is only allowed for yoooclaw_app sessions, the target session doesn't belong to yoooclaw_app — the plugin deliberately fails closed on cross-channel chat.send, this isn't a bug;
  6. 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.jsonpending.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