Skip to content

调试与排错

看日志

插件在 Hermes 自身日志管线之外,额外用了一套 OpenClaw 风格的文件日志,按天写在:

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

YOOOCLAW_HERMES_LOG_DIR 可以覆盖日志目录。稳定版会在写文件、以及把记录交给 Hermes 上游日志 handler 之前,脱敏常见的密钥、用户文本、用户 URL、邮箱、手机号、bearer token、JWT 和长十六进制 token;版本号里带 beta 的构建会保留原始日志,方便调试(和 OpenClaw 插件的行为一致)。排错时要留意:脱敏可能把真正出问题的那个值(比如 api-key 的某个片段)也一起遮住了,需要看原始值时确认插件版本号是否带 beta。超过 30 天的日志会自动清理,用 YOOOCLAW_HERMES_LOG_RETENTION_DAYS 调整保留天数。

通过 Hermes 插件 CLI 检索日志:

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

Hermes 托管的前台 daemon 子进程的 stdout/stderr 单独写在:

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

自更新安装日志单独存放:<state_root>/hermes-plugin/update/update.log,退出码在同目录的 exit_code 文件里。

Lifecycle 诊断

升级或连接异常时,先看 lifecycle 状态:

bash
hermes yoooclaw lifecycle status

重点看当前 daemon 是否宣称 owner=hermes-pluginingressMode=proxied,以及 generation 是否匹配当前插件版本 / profile / Relay environment / api-key。不匹配时插件本该自动重启服务组;如果没有,手动触发一次:

bash
hermes yoooclaw lifecycle restart

generation 是插件版本、内置 CLI 二进制哈希、当前 profile、Relay environment、Relay URL、api-key 指纹、ingress 模式和本地 egress callback URL 一起算出的 SHA-256。任何一项变化都会让 generation 对不上,触发插件接管/重启。

lifecycle status 里的 status 字段有三种取值,含义不同:

状态含义watchdog 行为
mismatchdaemon 存在但 owner/generation/ingressMode 对不上,或 daemon 根本没有 lifecycle 元数据(比如用户手动执行了 yc daemon start触发接管重启
unknowndaemon status 探测本身失败(不是"未运行",是探测不到结果)视为可容忍的瞬时噪音,不会立即重启,需要连续出现达到 YOOOCLAW_HERMES_LIFECYCLE_MISMATCH_STREAK(默认 2 次)门槛
daemon 子进程意外退出watchdog 检测到自己拥有的进程 exit,绕过 mismatch-streak 阈值立即重启整个服务组(区别于用户主动 daemon stop 的预期退出,靠内部 _owned_process_seq 计数区分)

环境与 Relay 排查

bash
hermes yoooclaw env             # 当前 profile + Relay 状态
yoooclaw auth show               # api-key 是否就位(与插件共享 credentials.json)
yoooclaw tunnel status            # 底层 CLI 视角的隧道连接状态

因为 daemon 以 --ingress proxied 跑在 Hermes 里,它自己不开 Relay 隧道,tunnel status 看到的是本地 sidecar 视角;实际的 openclaw-service 连接由插件的 OpenClawRelayTransport 维护,状态以 lifecycle status 和插件日志为准,不要只看 CLI 侧的隧道状态就判断连接是否正常。

PHONE_NOTIFICATIONS_ENV 解析优先级:显式设置的环境变量 > 当前 profile 的 relay host(若 CLI 版本 ≥ 0.2.4,会读取该变量并覆盖内置默认 host) > 兜底 production。传了一个未知值不会报错,会静默回落到 production——如果发现环境切换「看起来没生效」,先确认变量拼写。

常见错误信息对照

以下是插件代码里会抛出的原始错误信息(含 code),可以直接拿关键字去日志或对话里搜:

错误信息code触发场景处理
Embedded YoooClaw CLI is not available for <os>/<arch>.YOOOCLAW_CLI_UNSUPPORTED_PLATFORM当前平台没有内置的 CLI 二进制(仅支持 darwin-arm64/x64、linux-arm64/x64、win32-x64)确认运行平台是否受支持
Embedded CLI binary is missing: <path>.YOOOCLAW_CLI_BINARY_MISSING内置二进制文件丢失重新安装插件
Embedded CLI checksum mismatch: <path>.YOOOCLAW_CLI_CHECKSUM_MISMATCH内置二进制被篡改或安装损坏见下文「CLI 校验和不匹配」
YoooClaw CLI timed out after <n>s.YOOOCLAW_CLI_TIMEOUT调用内置 CLI 子进程超时检查 daemon 是否卡死,或加大超时
Could not find \yc`, `yoooclaw` in PATH.`YOOOCLAW_CLI_NOT_FOUNDPATH 里既没有内置 shim 也没有本地开发环境的 yc/yoooclaw检查 YOOOCLAW_HERMES_INSTALL_CLI 是否被设为 0,或 YOOOCLAW_CLI_PATH 指向了不存在的路径
YoooClaw daemon did not become ready within <n>sdaemon 子进程在 ready_timeout_seconds(默认 25s)内没有就绪,会被强制终止,避免进程泄漏hermes yoooclaw lifecycle statusdaemon.lastError,通常是端口占用或宿主环境异常
YoooClaw daemon did not reach the expected proxied lifecycledaemon 起来了但没能进入 proxied ingress 模式结合 daemon 日志排查,通常是配置或端口冲突
YoooClaw openclaw-service Relay api-key is missing没有配置 api-key 就尝试连接 Relayyoooclaw auth set-default-api-key
YoooClaw openclaw-service Relay authentication failed label=... : ... Update ~/.yoooclaw/credentials.json and reconnect.api-key 被拒绝(401/403/4401/invalid apikey),不会无限静默重试更新 credentials.json 里对应的 key,仅靠自动重连解决不了
Timed out connecting to YoooClaw openclaw-service Relay握手阶段超时检查网络连通性
YoooClaw Relay is disconnected / openclaw-service Relay is disconnected尝试在没有已连接隧道时发送帧等待重连,或手动 lifecycle restart
No active YoooClaw APP route for chat <id>目标 APP 会话没有对应的活跃连接确认 APP 端是否在线
YoooClaw egress callback server is not runningegress callback 本地 HTTP 服务未启动就被访问通常是内部时序问题,lifecycle restart
YoooClaw daemon is not running / YoooClaw daemon status did not include a portdaemon 桥接层找不到可用的 daemon先确认 daemon 本身状态
更新未执行:需要用户在对话中明确同意后,以 confirm=true 调用。YOOOCLAW_UPDATE_NOT_CONFIRMED模型调用更新工具时没有传 confirm=true需要在对话里明确同意后再次调用
当前插件是开发(editable/源码树)安装,拒绝自动更新;请在插件仓库里手动升级。YOOOCLAW_UPDATE_EDITABLE_INSTALL插件是 pip install -e 的可编辑安装手动在源码树里升级,不要走自更新
已有更新正在进行(目标版本 ...),请等待其完成。YOOOCLAW_UPDATE_IN_PROGRESS已有一次更新在跑等待完成;如果 pending.json 已经超过超时时间(默认 1800s)仍未清除,会被视为「陈旧」并自动放行新的更新
目标版本号不合法:<v>YOOOCLAW_UPDATE_BAD_VERSION传入的版本号格式不对检查版本号格式
当前版本 ... 已不低于目标版本 ...,无需更新。YOOOCLAW_UPDATE_NOT_NEWER目标版本不比当前版本新无需操作
下载安装器失败:<error>YOOOCLAW_UPDATE_INSTALLER_FETCH_FAILED从 OSS 拉取安装脚本失败检查网络,或稍后重试
启动更新进程失败:<error>YOOOCLAW_UPDATE_SPAWN_FAILED启动更新子进程失败检查权限与磁盘空间

常见症状 → 处理

hermes plugins enable yoooclaw 报错找不到插件

Hermes 0.15.1 及更早版本的 plugins enable/disable/list 只认目录形式插件,不扫描 Python entry points。直接编辑 ~/.hermes/config.yaml

yaml
plugins:
  enabled: [yoooclaw, yoooclaw_app]

hermes gateway restart。一键安装器已经自动写好这一步,只有手动 pip install 时才需要自己处理。

安装器报「Hermes 版本过低」直接中止

需要 Hermes Agent >= 0.14.0,因为 APP 适配器依赖的 PluginContext.register_platform 平台 API 更早版本没有。先升级 Hermes(hermes update),再重新跑安装器 —— 这是设计如此的硬性检查,不是安装器 bug。

安装器报「无法确定 Hermes 的 Python 环境」

安装器会尝试若干标准路径寻找 Hermes 使用的 venv Python,找不到就直接拒绝安装(不会装进一个通用 Python 环境,避免 gateway 之后 import 不到插件)。报错会列出它尝试过的路径。解决办法三选一:设置 HERMES_HOME;把 Hermes 自带的 hermes 命令加进 PATH;或者直接用 --python /path/to/hermes-agent/venv/bin/python 显式指定。

安装器报「Python 版本过低」

yoooclaw-hermes-plugin 要求 Python ≥ 3.11。检查 Hermes 使用的 venv 是用什么 Python 版本创建的,必要时重建 venv。

CLI 校验和不匹配(YOOOCLAW_CLI_CHECKSUM_MISMATCH

内置 CLI 二进制文件的哈希和插件包内 manifest.json 记录的不一致,通常是安装包损坏或文件被意外改动。插件会先尝试回退到之前缓存过的安装(按 mtime 取最新一份),如果没有可用的缓存就保持 PATH 不变(此时命令会报 YOOOCLAW_CLI_NOT_FOUND)。彻底解决需要重新安装插件。

APP 连不上 / 会话没反应

按顺序确认:

  1. yoooclaw auth show —— account 级 api-key 已配置,且和插件共享同一份 ~/.yoooclaw/credentials.json
  2. 环境变量里没有残留的 YOOOCLAW_APP_API_KEY / YOOOCLAW_API_KEY / YOOOCLAW_APP_ALLOWED_USERS / YOOOCLAW_APP_ALLOW_ALL_USERS / 已废弃的 YOOOCLAW_APP_RELAY_URL(安装器每次安装都会从 ~/.hermes/.env 里清掉这几个,但手动改过环境变量的话要自己查);
  3. hermes yoooclaw lifecycle status —— daemon owner/generation/ingressMode 都对得上;
  4. 插件日志里 --keyword relay 看有没有连接错误;
  5. 如果报的是 chat.send is only allowed for yoooclaw_app sessions,说明目标 session 不属于 yoooclaw_app —— 插件对跨渠道的 chat.send 会直接拒绝,不是 bug;
  6. 多设备场景下,同一个 api-key 的所有连接会收到同一条广播,每个 Hermes 实例各自处理一次,可能导致重复的响应帧——如果看到「同一条消息回复了两次」,先确认是不是跑了多个 Hermes 实例共用同一把 key。

Relay websocket 反复断开

适配器自带 watchdog:断连超过 YOOOCLAW_HERMES_WS_RESTART_AFTER(默认 30s)会自动重启服务组(短暂网络抖动不会触发整组重启),失败按指数退避重试(上限 YOOOCLAW_HERMES_LIFECYCLE_MAX_BACKOFF,默认 60s)。断连期间产生的 egress 事件(如 recording.status)会先缓冲(上限 100 条,TTL 60s,过期丢弃),重连后按顺序补发,不会丢最近的事件。如果一直卡在重连,通常是网络问题或 api-key 失效(401/403/4401/invalid apikey 都会快速失败而不是无限静默重试),而不是 watchdog 本身的问题;先用 yoooclaw auth show 确认 key 没过期。

如果重连一直失败但本地 daemon 是好的,watchdog 会独立恢复本地 daemon 并持续重试远端连接,不会出现「WS 断了、daemon 也被连带停掉」的死状态。

升级后插件行为没变 / skills 没更新

~/.hermes/skills/yoooclaw/ 是插件安装时复制进去的(不是软链接,因为 Hermes 不信任 site-packages 路径),带一个 .yoooclaw-managed 标记。如果这个目录已经存在但不是插件创建的(没有该标记),插件会打一条警告日志然后跳过覆盖,不会强制替换用户自己放的内容。升级后发现 skills 没更新,先检查这个目录是不是被手动改动过。

更新卡住 / 更新完没收到通知

自更新是异步的:旧进程里的 watcher 线程会持续把 update.log 流式推送到最后一次交互的 APP 会话,直到 exit_code 文件出现或超过超时时间(默认 1800s,超时按退出码 124 处理)。hermes gateway restart 由安装脚本自己触发,重载后的新插件进程会调用 resume_after_reload(),通过原子改名 pending.json → pending.claimed.json 保证新旧进程不会同时各发一次通知。如果长时间没反应,看 <state_root>/hermes-plugin/update/update.log 和同目录下的 exit_code 文件确认实际状态。

卸载插件

仓库里没有专门的卸载脚本。需要卸载时执行 pip uninstall yoooclaw-hermes-plugin,再手动从 ~/.hermes/config.yamlplugins.enabled 里移除 yoooclawyoooclaw_app,然后重启 gateway。

下一步