本文由 Codex 根据实际排查过程整理生成。

最近我在用一台 Mac 上的 Codex App 控制另一台 Mac mini。入口是在 Codex App 的 Devices you can control from this Mac。Mac mini 端已经打开了远程控制,但本机尝试连接时一直失败,界面只给出一句比较笼统的错误:

Failed to update connection

这个问题表面看像网络问题,实际根因是本机保存了一份已经被服务端撤销的 remote-control client 授权。下面是完整的排查和解决过程。

现象

当时的状态大概是这样:

  • Mac mini 上已经开启 remote control。
  • 两台机器在同一网络环境中,SSH 可以正常连到 Mac mini。
  • Mac mini 上 Codex App 和 app-server 都在运行。
  • 本机 Codex App 的设备列表里能看到 Mac mini,但点击连接时报 Failed to update connection
  • 重启 Codex App、重新开关 Mac mini 端 remote control 后,问题仍然存在。

这说明问题不太像普通的网络不可达,也不像 Mac mini 端服务完全没起来。

第一轮排查:确认 Mac mini 端是否正常

我先确认 Mac mini 端的几个基础条件。

通过 SSH 可以连上:

1
ssh mac-mini

继续检查 Mac mini 上的 Codex 进程,可以看到 Codex App、app-server 以及相关服务都在运行。再看 Codex daemon 的配置:

1
~/.codex/app-server-daemon/settings.json

其中:

1
2
3
{
"remoteControlEnabled": true
}

Mac mini 本地的 Codex SQLite 状态库中也能看到 remote control enrollment 记录,说明 Mac mini 作为被控端已经注册过环境,并且服务侧能发现它。

这一轮的结论是:Mac mini 端大体正常,问题更可能出在发起控制的这台 Mac 上。

关键线索:本机日志里的 revoked client

真正的突破来自本机 Codex App 日志。

日志目录大致在:

1
~/Library/Logs/com.openai.codex/

在最新日志中搜索 connection 相关错误时,发现了关键报错:

1
Remote-control client has been revoked

同时还能看到本机正在尝试连接某个旧的 remote-control host:

1
remote-control:env_e_...

这条信息非常关键。它说明:

  • 本机不是连不到 Mac mini。
  • Mac mini 端也不是没有响应。
  • 服务端明确拒绝了当前这个本机 remote-control client。
  • 这个 client 已经被撤销,但本机 Codex App 仍然在尝试复用它。

换句话说,Failed to update connection 只是 UI 层的泛化错误,真实原因是本机保存了一个失效的控制端授权。

为什么简单删除状态不够

本机 Codex App 的全局状态文件里有 remote control 相关记录:

1
~/.codex/.codex-global-state.json

里面包含:

  • remote-control client enrollment
  • 当前选中的 remote host
  • 已添加的 remote-control environment id
  • remote-control 自动连接状态

一开始我尝试直接清理这个 JSON 文件里的旧 enrollment。但问题是:Codex App 运行时会把全局状态读入内存,并在退出或状态更新时重新写回文件。

所以如果 Codex App 没有完全退出,直接改文件很容易被运行中的主进程覆盖。结果就是看起来删掉了,重开后旧 client 又回来了。

深入确认:device key 也要一起处理

为了确认 remote-control client 是如何保存的,我进一步检查了 Codex App 内部实现。

Codex App 的 Electron 资源里有 native 模块:

1
remote-control-device-key.node

它暴露了几个和设备密钥相关的方法:

1
2
3
4
createDeviceKey
deleteDeviceKey
getDeviceKeyPublic
signDeviceKey

也就是说,remote-control client 不只是 JSON 里的一段状态,还和本机保存的 device key 有关。旧 client 被服务端 revoke 后,如果本机继续拿同一个 client 和 key 去连接,就会一直被拒绝。

因此完整清理需要两部分:

  1. 删除本机 .codex-global-state.json 里的旧 remote-control enrollment 和连接状态。
  2. 删除对应的本机 device key。

解决方案:在 Codex 完全退出后清理旧授权

最终有效的做法是:等待 Codex App 主进程完全退出后,再清理本机旧 remote-control 授权。

清理内容包括:

  • electron-remote-control-client-enrollments
  • selected-remote-host-id
  • added-remote-control-env-ids
  • remote-connection-auto-connect-by-host-id 中所有 remote-control: 开头的条目
  • 与旧 enrollment 对应的 device key

清理前先备份:

1
2
cp ~/.codex/.codex-global-state.json \
~/.codex/.codex-global-state.json.remote-control-reset.bak

然后在 Codex App 完全退出后写回清理后的状态,并调用 Codex 自带的 native device-key 模块删除旧 key。这里涉及 Codex App 的内部状态,操作前一定要备份,并确认只清理旧 remote-control client 对应的 key;不确定时不要直接批量删除。

这一步完成后,再重新打开 Codex App。

验证结果

重开 Codex App 后,我做了几项验证。

本机状态已经变成干净状态:

1
2
3
4
5
6
7
{
"selected": null,
"addedCount": 0,
"autoRemoteControlKeys": 0,
"enrollmentCount": 0,
"enrollments": []
}

清理日志显示,旧 client 和旧 key 都已经移除。这里不贴完整 ID,只保留占位符:

1
2
removed client hash: <redacted>
deleted key hash: <redacted>

重新检查最新 Codex App 日志,之前的关键错误已经消失:

1
Remote-control client has been revoked

没有再出现。

同时,本机 app-server 初始化正常:

1
2
initialize_handshake_result outcome=success
Codex CLI initialized

Mac mini 端也再次确认:

  • remoteControlEnabled=true
  • Codex App 进程存在
  • app-server 进程存在
  • enrollment 表里仍能看到 mac-mini.local

这说明旧的 revoked client 问题已经解决。

最后一步:重新授权本机控制 Mac mini

清理之后,本机不再持有旧的 remote-control client,因此状态会变成“没有授权”。

这不是坏事,反而是预期结果。接下来需要在 Codex App 的 UI 里重新授权:

  1. 打开 Codex App 设置。
  2. 进入 Devices you can control from this Mac 或 Remote Connections 页面。
  3. 找到 Mac mini / mac-mini.local
  4. 点击 Add / Setup / Authorize
  5. 完成 ChatGPT step-up 授权。
  6. 再点击 Connect。

重新授权后,本机会生成新的 remote-control client 和新的 device key。这个新 client 没有被 revoke,就可以正常连接 Mac mini。

结论

这次问题的根因不是 Mac mini 端没开,也不是 SSH 或局域网不通,而是控制端这台 Mac 保存了一个已经被服务端撤销的 remote-control client。

UI 上看到的:

1
Failed to update connection

只是表层错误。真正应该看的日志信号是:

1
Remote-control client has been revoked

解决思路可以总结成一句话:

让 Codex App 完全退出,清掉本机旧的 remote-control enrollment 和 device key,然后重新打开 Codex App,对 Mac mini 做一次新的授权。

排查这类问题时,最好把“被控端是否正常”和“控制端授权是否有效”分开看。前者看 Mac mini 的 remote-control 开关、app-server 和 enrollment;后者看本机 Codex 日志、global state 以及 device key。这样就不会被一个笼统的 Failed to update connection 带偏。