故障排查
本文列出 Wesclaw 常见问题的诊断与修复方法。
Go 后端启动失败
症状
- Electron 白屏或"连接后端失败"
wesclaw rpc子进程未运行
排查步骤
-
查看日志
macOS: ~/Library/Application Support/wesclaw/logs/ Linux: ~/.local/share/wesclaw/logs/ -
初始化配置(首次使用)
wesclaw init # 编辑 config.yaml,填入 LLM Provider API Key -
检查数据目录权限 — 确保 XDG DataDir 有完整读写权限
-
引擎版本 — boot 日志应输出
sdk_version,若缺失说明启动未完成
Electron 更新超时
症状
- 更新后 Go 后端来不及释放资源,数据损坏
原因与修复
autoUpdater.quitAndInstall() 的 forceRunAfter 超时应设为 10s(而非 3s),给 Go 后端留出安全关闭窗口。
| 机制 | 说明 |
|---|---|
handleShutdown | 同步执行 StopEngine + CloseStore,RPC 返回时资源已释放 |
INV-RESIL-04 | Cell 进程排他锁(flock .cell.lock),防止重复写入 |
| Boot 降级 | 即使数据损坏,Boot 返回 nil error(降级合法),不阻塞启动 |
wesclaw.db 迁移失败
症状
- 启动后应用数据(对话/技能/设置)被清空
机制(INV-MIGRATE-01)
wesclaw.db 使用 PRAGMA user_version 驱动迁移链:
Boot → 读 user_version → 按序执行未应用的 MigrationStep
→ 每步一个事务(DDL + version 递增)→ 全部成功 → DB 可用
降级策略:迁移失败 → 归档旧文件为 .migration-failed → 清除 WAL/SHM → 全新 DB → 重跑迁移 → 二次失败才 fatal。
三链共存
wesclaw.db 上运行三条独立迁移链,互不干扰:
| 链 | 策略 | 管理的表 |
|---|---|---|
Chain 1 store.RunMigrations | PRAGMA user_version | tc_conversations 等 8 表 |
Chain 2 group.Migrate() | IF NOT EXISTS + 列检测 | tc_groups 等 4 表 |
Chain 3 auth.Migrate() | IF NOT EXISTS + DEV-1 | tc_session |
Cell 锁竞争
症状
- 启动失败,日志显示
ErrCellLocked
原因
同一 Cell 同一时刻只允许一个写入者(flock .cell.lock,INV-RESIL-04)。
解决
- 确认是否有残余
wesclaw进程仍在运行 - macOS:
ps aux | grep wesclaw;Linux:同理 - 杀掉残余进程后重试
SSE 断流
症状
- 对话中途连接断开,但 AI 仍在工作
设计(INV-RUN-DETACH)
Run 生命周期与 SSE 连接完全解耦。SSE 断开不会取消 Run。
| 行为 | 说明 |
|---|---|
| 断开后 Run 继续 | Run 独立于传输层运行 |
| 重连续播 | GET /runs/{runID}/events?from_seq=N |
| 终止手段 | POST /sessions/{sid}/interrupt(用户主动) |
chatInFlight 锁
同一时刻最多一个可见生成轮次,锁在 done/error/interrupted 事件到达时释放:
发送 → 加锁 → 流式响应 → 终端事件 → 释放锁
若卡住:使用 interrupt 端点中断当前 Run。
IM 渠道收不到消息
排查步骤
-
Webhook URL 格式
每个 Cell 使用独立 URL:
POST /cells/{cellID}/webhook/wecom POST /cells/{cellID}/webhook/feishu POST /cells/{cellID}/webhook/dingtalk -
预检验证
POST /cells/{cellID}/channels/preflight -
检查渠道配置 —
GET /cells/{cellID}/channels确认凭证正确 -
SeedSpec 注意 —
CellSpec.Channels是出生声明,首次 boot 后存储为权威源
Provider 连接失败
排查步骤
-
测试连通性
POST /cells/{cellID}/providers/test {"provider": "my-openai", "mode": ""} # mode: 空=chat, "embedding", "vision" -
SecretRef 来源
Source 说明 inline明文经 AES-256-GCM 封套后落盘 env从环境变量读取 live运行时动态注入(WES/Org) -
WES vs BYOK
- WES 模型依赖平台 JWT,过期后自动失效并 fallback 到 BYOK
- BYOK 密钥本地存储,不受 WES 状态影响
模型选择器为空
排查步骤
- 确认 Provider 已配置 — 至少配置一个可用 Provider(WES 登录或 BYOK)
- 检查 Models 声明 — Provider 必须声明
Models[],含context_window - Catalog 来源 —
weisyn.ProviderCatalog()(catalog.yaml)是唯一模型数据源 - 前端单一 RPC —
sidebar/availableModels统一返回所有可用模型 - 发送条件 —
selectedModel == ""时发送按钮 disabled(INV-MODEL-02)
WES 欠费处理
| 场景 | 发送 | 提示 |
|---|---|---|
| WES 欠费 + 有 BYOK + 选 BYOK | ✅ 正常 | 无 |
| WES 欠费 + 有 BYOK + 选 WES | ❌ 阻断 | 引导切换 BYOK |
| WES 欠费 + 无 BYOK | ❌ 阻断 | 引导充值或配置 BYOK |
关键:已选 BYOK 时不得禁用输入或显示"请切换到自有模型"(INV-CHAT-02/04)。
日志位置
| 日志 | 路径 | 内容 |
|---|---|---|
| Go 后端 | $WESCLAW_DATA_DIR/logs/ | 引擎运行日志 |
| Electron | $WESCLAW_DATA_DIR/logs/{timestamp}/ | 窗口日志 |
| Chat 管道 | $WESCLAW_DATA_DIR/logs/wescode-chat.log | RPC send/recv + Webview 事件 |
| 引擎崩溃 | $WESCLAW_DATA_DIR/crashes/ | panic 栈(fd 2 dup2 到文件) |
macOS 路径示例:~/Library/Application Support/wesclaw/
版本升级注意事项
- 引擎版本只升不降 — 旧引擎读新格式 spec 可能导致 Cell 目录被归档
- 升级前备份 —
Cell Export或手动备份cells/main/目录 - tc_ 表清空* — 升级到含
cell_id列的版本时,应用数据会一次性清空 - Boot 安全 — 即使迁移失败,Boot 仍会成功(降级模式)
- 日志确认 — 升级后检查
sdk_version日志确认版本正确
快速诊断清单
# 1. Go 后端是否存活
ps aux | grep wesclaw
# 2. 健康检查(桌面版无 HTTP,用 RPC 冒烟)
make rpc-test
# 3. 数据目录检查
ls -la ~/Library/Application\ Support/wesclaw/
# 4. 日志查看
tail -100 ~/Library/Application\ Support/wesclaw/logs/*.log
# 5. 构建检验
go build ./... && go vet ./...
cd apps/desktop/web && npx tsc --noEmit -p tsconfig.app.json