排错与诊断
TIP
遇到问题时,先确定故障发生在哪一段链路,再动配置。HTTP 有响应、界面提示保存成功、能拉到模型列表、甚至流式打出几个字,都不代表整条对话链路已经跑通。
本页按故障现象组织。不需要一上来就清空数据库、重装依赖或放开全部权限,按步骤逐层定位即可。
先收集证据
改配置或求助之前,先记下:
- 发生时间与复现步骤。
- ChatLuna 版本、部署方式、实例名称或目录。
- 出错的页面、平台和会话 ID。
- 完整的错误信息、错误码和最近一次配置变更。
- 服务端日志和浏览器控制台报错。
DANGER
分享日志前,删掉 Authorization 请求头、访问令牌、API Key、平台凭据、用户聊天内容和工具输出。不要直接分享整个运行环境或含有私密信息的 chatluna.yml。
已有实例目录时,先跑静态诊断:
chatluna list
chatluna doctor config --dir .源码工作区中可以用 yarn chatluna 运行同样的命令。doctor config 只做本地静态检查,不会去请求远端模型。
启动失败或配置未生效
1. 确认生效的是哪个文件。 --dir 优先级最高;命令行传了实例名时,使用受管目录而不是当前目录。指定目录后,按 cordis.yml、cordis.yaml、chatluna.yml、chatluna.yaml 的顺序查找根清单。清单用了 include 时,顺着引用链确认你改的文件确实在生效链路上。
2. 检查清单。
- YAML 缩进是否正确。
- 每个条目是否有唯一稳定的
id。 - 引用的插件包已安装,且没有
disabled: true。 - 插件
inject声明的服务都已加载。
3. 检查构建产物。 改了源码或新增依赖后要重新 yarn build。启动时报 ERR_MODULE_NOT_FOUND,通常不是路径配置的问题,而是对应包的 lib 产物还没生成。
chatluna dev . 用 oxc-node 直接加载源码并热重载,但不启用守护进程的崩溃恢复和安全模式,排查时注意区分启动恢复报告和普通的业务异常。热重载后出现重复监听或工具重名,说明有资源没有绑定到插件生命周期,应该修复绑定,而不是用全局 Set 之类的手段掩盖泄漏。
WARNING
chatluna repair 可能修改工程文件,执行前先读诊断报告并备份。chatluna report 只查看本地已有的报告和 Issue 草稿,不会发送任何内容。
WebUI 打不开或离线
| 现象 | 优先检查 |
|---|---|
| 连接被拒绝 | 进程是否存活、监听地址与端口、Docker Compose 服务状态 |
| 401 | 登录会话过期、令牌已更改、反向代理丢了认证头 |
| 403 | allowRemote 来源限制、权限等级,不一定是口令错误 |
| 404 | 访问路径、插件路由、前端产物、反向代理的前缀重写 |
| 显示旧数据但无法操作 | WebSocket 已断开,页面只是断线前的快照 |
| 只有某个页面打不开 | 对应的页面包、前端入口产物、依赖的服务 |
在可信的本机上测试健康检查端点(5028 换成实际端口):
curl --fail http://127.0.0.1:5028/api/health它只证明 HTTP 服务活着,不代表模型服务、聊天平台、存储插件和 WebSocket 都可用。
网络方面注意:
- 控制台的 state/action、对话持久化的 Durable SSE 和实时的 Live SSE 是彼此独立的通道,不能只看其中一条判断整体状态。
- 反向代理必须转发 WebSocket 握手,并对流式接口关闭缓冲。
- 官方 Compose 默认只把端口绑到宿主机的
127.0.0.1。远程访问时,检查宿主机地址、监听配置、来源限制和 HTTPS 证书,不要靠关闭认证来测连通性。
忘记访问令牌
先确认令牌来自哪里:server 配置、CHATLUNA_TOKEN 环境变量,还是文件模式。
- 固定令牌:在原配置或环境变量中修改。只删
auth.json没用,静态配置仍然生效。 - 文件模式:
auth.json只存哈希和签名密钥,无法反查明文。停止实例、备份数据后删除auth.json并重启,从启动日志中拿新令牌。已有的登录会话会全部失效。 - 弱令牌:强度不够的固定令牌会被忽略,回退到文件模式。看启动日志中实际生效的令牌,不要反复试那个弱令牌。
DANGER
不要通过删除整个数据目录来重置令牌,也不要在公开场合分享首次登录链接。
模型已配置却不回复
按以下顺序自底向上排查:
- 提供商插件:对应的提供商插件是否已安装并加载。缺了它,相关配置不会变成可用模型。
- 实际使用的模型:检查生效规则、预设或会话绑定的
provider:model,不要只看全局默认。 - 凭据与端点:API Key、接口地址、模型名、组织和区域。界面中留空凭据表示保留原值,不是清空。
- 真实推理:能拉到模型列表只说明凭据通过了元数据探测,要发一次真实对话才算通。
- 能力匹配:模型是否支持当前场景需要的多模态、工具调用或附件。
chat、embed、decide是不同的能力,不能互相替代。 - 配额与状态:
finish_reason、供应商错误码、超时、配额和余额。
实例运行时可以直接诊断提供商连通性(连接信息可以通过 CHATLUNA_BASE 与 CHATLUNA_TOKEN 提供):
chatluna doctor providers --dir .WARNING
请求被取消、网络中断或超时,只要供应商已经开始计算,通常照样计费。
平台在线但不回复
平台在线只代表适配器和平台网关连上了。接下来检查:
回复条件。 先看场景规则中的引擎、预设、模型和会话归属,再逐项核对:
- @、叫名字、引用回复、随机回复和私聊直接回复是各自独立的开关。
- 通用回复条件中
allowQuoteReply默认为false,不开启时引用机器人的消息不会触发回复。 - 冷却时间、机器人自身消息过滤、角色引擎的判断都可能提前中断回复。
- 未触发的消息只会被记录用来维护上下文,不会发起推理。
会话路由与投递。 多机器人、多平台或群聊私聊混用时,消息可能被分到不同的会话,检查命中的规则。模型推理成功不代表消息已经送达,还要看渲染和投递阶段的日志。
TIP
排查时用独立的测试账号和会话,不要让 v1 和 v2 同时连接同一个机器人账号。首次人设访谈只能由主人在私聊中触发,群聊中唤不起来是正常的。
绑定码或新手引导卡住
引导的三步有依赖关系:模型必须通过真实推理测试,平台必须有在线的非网页机器人,才能进入用途设定。点击「跳过」不代表依赖已经满足。
绑定码的规则:
- 必须在真实聊天平台的私聊中发送
bind <code>(是否需要/前缀取决于指令配置),不能在 WebUI 的聊天窗口中绑定。 - 主人身份按实际发送这条消息的平台账号确定。
- 有效期 10 分钟;生成新码后旧码立即失效;连续输错 5 次作废。
- 普通用户私聊机器人不会自动获得主人身份。
主人状态、引导完成状态、模型就绪状态、当前预设和人设数据是分开存储的。执行 setup 后,从下一条消息开始进入访谈。以指令的实际反馈为准,不要随手清空预设数据。
预设保存后未生效
- 变量区域:
system区只能用静态变量,动态值放在context区。报MutableVariableError说明放错了区域,系统不会降级渲染。 - 包含语法:引入局部模板必须单独一行写
@include ./partial.md,其他写法不会被识别。 - 版本冲突:外部编辑或多端同时保存会触发版本冲突,重新拉取后手动合并,不要强行覆盖。
- 生效时机:修改只对保存之后的新轮次生效,不影响已经发给模型的请求。
- 监听缓存:文件监听器解析失败时会保留上一次成功的版本,磁盘上的文件变了不代表内存中的预设已经更新。
工具不见、反复询问或被拒
按「可见性 → 策略 → 执行」的顺序:
- 注册:提供工具的插件和服务是否启用,工具是否已注册。
- 允许列表:检查预设或场景中的允许列表与工具策略。「配置为空列表」和「没有配置」是两种不同的行为。
- 延迟加载:延迟加载的工具要先被搜索命中才会出现,首轮提示词中看不到不代表丢失。
- 参数校验:看实际传给工具的 JSON 参数是否符合 Schema,不要信模型自己的解释。
- 权限:调用者的
level、作用范围,以及ask审批通道是否就绪。 - 策略:
自动只是不再二次确认,仍然要过权限等级和审批规则;禁用只隐藏工具,不会卸载插件。 - 执行:本地环境、MCP 连接或下游 API 是否正常。多数失败发生在执行阶段,而不是被框架拒绝。
DANGER
审批超时或没有审批通道时,默认按拒绝处理。不要为了省掉审批,把所有工具设为 auto、把所有用户提到等级 5,或把宿主机的 Docker Socket 挂进容器。
记忆、定时任务与后台作业
长期记忆
- 新建或重置会话不会清空长期记忆。排查召回时,区分
scopes作用域、后台索引和检索结果。 - 自动提取记忆默认关闭。
index通知只代表检测到主题变化,不代表全文被拼进了提示词。 - 开启会话隔离,不等于工具搜索有严格的私有数据边界。
定时任务
- 必须有真实注册的任务和执行日志,不能只凭机器人说「已设置提醒」。
- 检查时区、暂停状态、
when表达式、grace容错窗口、超时和结果投递目标。 wakeup任务的messages只包含上次唤醒以来的新消息;表达式解析器不是通用的 JavaScript 环境。
后台作业
- 最终状态可能是
failed或cancelled。收到占位提示或进入settled,不代表业务已经成功。 - 重启后不会接管之前未完成的作业。
- Docker 中
pause保留容器进程和内存,close直接销毁容器。恢复前确认工作区和产物已经持久化到宿主机。
历史、轨迹与用量对不上
- 序号:存储中的
Session n是存储序列的条目号,不是页面上的消息下标。 - 视图:页面会去掉内部标记
mark,并受cut截断和摘要压缩影响。分叉复制使用半开区间;逻辑上的 Head 和存储层的分支不在同一层。 - 回放:
reconstruct只在本地重组提示词,不调用模型、不产生费用;replay会发起新的推理并计费,但不会重新执行原来的外部工具。 - 流式状态:
live是未完成的中间文本,不是已提交的committed消息。中断变成truncated时,通过接口拉取完整的messages快照重置视图,不要把截断的文本当成完整历史保存。 - 用量口径:Token 统计、供应商账单、成本估算和控制台的
active列表口径不同。有些供应商的输入输出数已经扣除了缓存或包含了推理 Token,再累加就会偏大。核对前先检查计费插件配置、模型单价和统计周期。
提交问题前
仍然解决不了时,提交 Issue 请附上:
- 最小的复现步骤。
- 预期行为与实际现象。
- 发生时间、完整版本号和错误码。
- 插件清单,以及脱敏后的服务端日志和浏览器报错。
- 是否能在全新实例中复现、是否刚升级过、回退版本后是否仍然存在。
DANGER
不要把数据库文件、auth.json、完整的环境变量导出或含有真实用户隐私的对话作为附件上传。