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 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 three things: whether components.mode is daemonless, whether daemon.storage.claimed is true (this process holds the writer lock), and whether generation matches the current plugin version / profile / Relay environment / api-key. A mismatch should make the plugin rebuild the group automatically; if it doesn't, trigger it manually:

bash
hermes yoooclaw lifecycle restart

The generation is a SHA-256 (first 24 hex chars) computed from the plugin version, active profile, Relay environment, PHONE_NOTIFICATIONS_ENV, openclaw-service URL, and api-key fingerprint. Any of those changing means the generation no longer matches, which triggers a rebuild.

lifecycle status's status field:

StatusMeaningWatchdog behavior
runningTunnels connected and the generation matches the current configNo action
stoppedNo registered transport (the plugin isn't connected, or has disconnected)No action
mismatchThe generation doesn't match the current config, or a lifecycle restart was requestedRebuilds the tunnels (disconnect + connect) on the next poll, by default within 5 seconds; requires YOOOCLAW_HERMES_LIFECYCLE_MISMATCH_STREAK (default 2) consecutive readings to avoid over-reacting to probe noise

The daemon field name is kept for compatibility with existing lifecycle.json consumers, but its contents are now the storage-claim state (mode: daemonless plus storage.{claimed,profileDir,writerLock}) — there is no daemon process information in it.

Environment & Relay checks

bash
hermes yoooclaw env              # current profile + Relay status
yoooclaw auth status             # is the api-key in place (shared credentials.json with the plugin)

Don't look at yoooclaw tunnel status in plugin mode

The tunnel lives inside the plugin process; on the CLI side there is neither a daemon nor a tunnel. The actual openclaw-service connection is maintained by the plugin's OpenClawRelayTransport, so only lifecycle status and the plugin logs reflect reality. Likewise, yoooclaw daemon start returns YOOOCLAW_DAEMON_DISABLED_BY_PLUGIN while the plugin holds the lock — that's expected, not a failure.

The cloud host (shared by the tunnel, light effects, light rules, and ASR) resolves in this order: PHONE_NOTIFICATIONS_ENV and friends > cloud.host > the domain in relay.url > the built-in production default. An unrecognized env 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, then look at cloud.host in yoooclaw config show. Full rules in Standalone CLI: Environment / host mismatch.

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 the plugin log for which command it was, and raise the timeout if needed
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
profile writer lock is held by another process: <path>Another process holds the storage writer lock (usually a still-running yoooclaw daemon, or a second Hermes instance)Stop that process, then hermes yoooclaw lifecycle restart. A failed claim doesn't block chat — ingest just takes the fallback path
YOOOCLAW_NOT_IMPLEMENTED on recordings.retranscribe / asr.initYOOOCLAW_NOT_IMPLEMENTEDPlugin mode doesn't run ASR locallyExpected: in the Hermes setup transcription happens on the App side and arrives via recordings.result.write
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 daemon is not running / YoooClaw daemon status did not include a portOne of the few paths that still falls back to daemon HTTP found no daemon (there normally isn't one in daemonless mode)Confirm storage.claimed is true in lifecycle status; once the claim succeeds these paths aren't reached
更新未执行:需要用户在对话中明确同意后,以 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 status — 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 statusstatus=running, storage.claimed=true, and the generation lines 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 rebuilds the whole service group once disconnection exceeds YOOOCLAW_HERMES_WS_RESTART_AFTER (default 30s — a brief network blip won't trigger a full rebuild), retrying failed recoveries with exponential backoff capped at YOOOCLAW_HERMES_LIFECYCLE_MAX_BACKOFF (default 60s). 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 status first.

A dropped tunnel doesn't affect local storage: the plugin still holds the writer lock, so read-only commands like yoooclaw notification search keep working.

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

  • Usage & Lifecycle — environment switching, lifecycle management details.
  • Standalone CLI Debugging — the storage layout, cloud host resolution, and Relay protocol are shared, so much of the troubleshooting carries over.