第 11 章 常见问题与排错手册
本章汇总初学者最容易遇到的问题,答案均来自官方文档与教程。
11.1 插件没有输出 / "好像没生效"
按顺序排查:
检查拼写。如果配置项的模块无法被解析(路径或包名拼错),Cordis 会通过 logger 服务报告错误而不崩溃,且启动早期这条报告可能在 console 导出器开始观察之前丢失。这是"新增配置项毫无效果"的头号原因。
检查 fiber 状态是否 PENDING。
inject指定了无人提供的服务时,插件会一直静默等待——这是合法状态,不是错误。用第 7 章的diagnose.ts遍历ctx.registry查看FiberState.PENDING的插件。PENDING 不会保持进程存活。如果组合里没有其他运行项,进程会静默以状态码 0 退出——看起来像"什么都没发生"。
HMR 没消息? HMR 插件依赖 logger 服务(没装 console logger 就看不到日志)和 timer 服务(没有 timer 就永远 PENDING)。
apply 抛异常会明确崩溃,所以"毫无反应"通常不是 apply 的错,而是根本没被加载。
11.2 配置相关问题
| 现象 | 原因与解法 |
|---|---|
ValidationError: invalid config | 配置未通过 schema 校验,fiber 进入 FAILED;按报错路径(如 $.targets)修正 YAML |
导出普通对象作为 Config 不生效 | Cordis 只接受 Standard Schema 验证器;dsh 用 Schemastery,需导出 Schema.object({...}) |
!!js 表达式没被求值 | !!js 仅在 config 与条目 disabled 字段内有效;其他元数据是字面值 |
编辑 cordis.yml 后所有条目都重新挂载 | 条目缺少显式 id,每次读取都获得新 id,被当作"先删除再添加" |
| 想临时停用某插件 | 给条目加 id 并设 disabled: true,保留条目、跳过挂载 |
11.3 生命周期相关
| 现象 | 原因与解法 |
|---|---|
| 资源在热重载后泄漏(定时器/连接未清理) | 在 Cordis API 之外创建的资源必须包进 ctx.effect() 并返回 disposer |
| disposer 执行顺序错乱 | disposer 按注册逆序启动,但异步 disposer 并发运行;有顺序要求时放进同一个 disposer 依次 await |
| 服务消失后消费方还在用旧引用 | 不会——依赖插件会随服务卸载而卸载、恢复后重载;若出现此类问题,检查是否用了 ctx.get() 的可选依赖 |
| 监听器越积越多 | 不会——ctx.on() 是 effect,随插件卸载自动移除 |
11.4 Waterfall 相关
最重要的规则:只做观察/标注的 waterfall 监听器必须调用 next()。不调用 next() 直接返回 = 有意短路,会吞掉下游所有默认行为。如果某条流水线(如 tools/*、agent/request)的行为突然"消失",检查是否新加了忘记委托的监听器。
区分两类事件:
agent/pre-step、agent/request、llm/stream、tools/pre-execute|execute|post-execute→ waterfall,有next();agent/turn-stopping→ serial,没有next()。
11.5 查看运行中的配置
打印启动时的完整配置树;它输出的任何条目都可以被你自己的 patch 替换(patch 按 id 定位条目并替换其整个 config,或插入新条目)。注意 headless/sdk/sdk-minimal/acp 只在启动时应用一次配置层,不支持运行中热重载 patch。
11.6 学习资源索引
提示:dsh 目前处于技术预览(Technical Preview)阶段,API 可能随版本演进调整;遇到与本文不符的行为,请以官方文档对应版本为准。
本知识库全文依据官方文档与教程整理,供学习参考。