问题
_poll_once() 检测到 session 过期(errcode -14)后会设置 60 分钟暂停并 sleep。但醒来后直接 return,没有调用 _load_state() 重新读取 account.json。后续轮询继续使用内存中的过期 token,反复命中 errcode -14,形成永久静默的死循环。
复现
nanobot channels login weixin扫码登录- 等待 session token 自然过期(约 2 小时)
- 微信频道永久静默 — 不重新扫码就无法恢复
修复
在 pause sleep 之后调用 self._load_state(),从 account.json 重新加载 token。这样通过 channel rebinding 等方式刷新的 token 能被立即拾取。
变更
nanobot/channels/weixin.py:+1 行
if remaining > 0:
await asyncio.sleep(remaining)
+ self._load_state()
return影响范围:所有长期运行的 weixin 频道实例。
Activity
5很奇怪哦,我的微信channel一直在跑, 貌似并没有永久静默
很奇怪哦,我的微信channel一直在跑, 貌似并没有永久静默
@chengyongru 感谢 review!
不是"立即静默",是 60 分钟周期的死循环,所以从外部看 bot 仍然"在线",只是不再收发消息:
复现路径
- session token 过期(有效期由微信服务器决定,与具体 token 类型有关)
_sync_check()返回 errcode -14- 设置
_session_pause_until = now + 3600,sleep 60 分钟 - sleep 结束后直接
return,不重新加载 account.json - 下次
_poll_once用内存中仍过期的 token 再次命中 -14 → 回到第 3 步
为什么你没遇到
- 定期重启 bot(commit 新代码、重启容器等)会使 pause 计数器和 token 同时重置
- 开发环境频繁开关通道,token 来不及自然过期
- 生产环境长时间运行的实例才触发
发现过程
我们在实现微信 channel 的 web 端自助绑定(/bind/wechat)时碰到:
- 用户重新扫码绑定微信 →
account.json写入新 token ✅ - 但 bot 仍不接收消息 ← 检查日志
- 发现 errcode -14 → pause 60min → sleep 完直接
return→ 再次 -14 → 循环 - 重启进程立即恢复(因为启动时调用了
_load_state())
根因:_poll_once 用的是内存里缓存的过期 token,不会重读 account.json 里刷新后的新 token。
修复价值
不光是解决死循环——更重要的是让 web bind 刷新的 token 能被运行时立即拾取。没有 _load_state(),即使通过 /bind/wechat 重新扫码写入了新的 account.json,_poll_once 依然用内存里的旧 token。
验证方式
不需要等 token 自然过期,直接模拟即可:
- 手动删掉 account.json 里的 context_tokens / typing_tickets
- 下一次 _sync_check 会触发 -14 → 进入 60 分钟 pause
- 60 分钟后醒来,无 _load_state() → 兜回 -14 → 再睡 60 分钟
- 修了之后:醒来→加载 account.json→拾取新 token→恢复正常
很奇怪哦,我的微信channel一直在跑, 貌似并没有永久静默
@chengyongru 感谢 review!
不是"立即静默",是 60 分钟周期的死循环,所以从外部看 bot 仍然"在线",只是不再收发消息:
复现路径
- session token 过期(有效期由微信服务器决定,与具体 token 类型有关)
_sync_check()返回 errcode -14- 设置
_session_pause_until = now + 3600,sleep 60 分钟 - sleep 结束后直接
return,不重新加载 account.json - 下次
_poll_once用内存中仍过期的 token 再次命中 -14 → 回到第 3 步
为什么你没遇到
- 定期重启 bot(commit 新代码、重启容器等)会使 pause 计数器和 token 同时重置
- 开发环境频繁开关通道,token 来不及自然过期
- 生产环境长时间运行的实例才触发
发现过程
我们在实现微信 channel 的 web 端自助绑定(/bind/wechat)时碰到:
- 用户重新扫码绑定微信 →
account.json写入新 token ✅ - 但 bot 仍不接收消息 ← 检查日志
- 发现 errcode -14 → pause 60min → sleep 完直接
return→ 再次 -14 → 循环 - 重启进程立即恢复(因为启动时调用了
_load_state())
根因:_poll_once 用的是内存里缓存的过期 token,不会重读 account.json 里刷新后的新 token。
修复价值
不光是解决死循环——更重要的是让 web bind 刷新的 token 能被运行时立即拾取。没有 _load_state(),即使通过 /bind/wechat 重新扫码写入了新的 account.json,_poll_once 依然用内存里的旧 token。
验证方式
不需要等 token 自然过期,直接模拟即可:
- 手动删掉 account.json 里的 context_tokens / typing_tickets
- 下一次 _sync_check 会触发 -14 → 进入 60 分钟 pause
- 60 分钟后醒来,无 _load_state() → 兜回 -14 → 再睡 60 分钟
- 修了之后:醒来→加载 account.json→拾取新 token→恢复正常
很奇怪哦,我的微信channel一直在跑, 貌似并没有永久静默