常见问题排查
从症状出发,找到下一步该运行的命令。内容按通常会遇到的顺序排列:先是启动与认证,然后是请求失败、会话、TUI 渲染和性能。
先在终端运行 chord --version,确认命令能找到且程序可以启动。下载的二进制不需要 Go;只有源码构建才需要检查 Go 版本和启动入口。
- 命令找不到或被系统阻止:检查安装路径;macOS 下载版的处理步骤见快速开始。
- 配置缺失:在交互式终端运行
chord,按初始化向导配置。 - 配置错误:运行
chord doctor config,根据报告修正 YAML 或字段。 - 仍无法启动:保留终端错误输出,再查看本页末尾的日志采集说明。
初始化向导只在 config.yaml 缺失时运行,不会覆盖已有的损坏配置。没有控制终端时会返回初始化错误,应先在交互式环境完成配置。
401 / 403 / 认证失败
Section titled “401 / 403 / 认证失败”检查:
auth.yaml中 provider 名称是否与config.yaml对应- API key 是否有效
- OAuth provider 是否配置了
preset: codex
可以用以下命令排查:
chord doctor models如果要缩小到明确的模型或模型池:
chord doctor models --model openai/gpt-5.5@highchord doctor models --pool thinking429 / quota exhausted
Section titled “429 / quota exhausted”常见原因:
- key 已达配额上限
- provider 限流
- 并发或高频请求触发了速率限制
建议:
- 换一个 key
- 降低并发或减少重试
- 检查是否存在异常循环调用
如果要判断哪些 key 或模型反复限流 / 报错:
- 在 TUI 的 Normal 模式下按
Ctrl+E打开错误面板;这里会记录包含 429 在内的重试错误,并显示 provider、model 和打码后的key=...标识。 - 看错误面板里的模式:如果总是同一个 key 返回 429,通常是这个 key 被限流;如果同一 provider 的多个 key 都返回 503,更可能是 provider 侧异常。
界面说明:
- 右侧 RATE LIMIT 面板展示的是 Codex 最近一次用量/限流快照(如
5h: 42% 2h30m)。到达 reset 时间点后倒计时会短暂消失,Chord 触发一次用量刷新;由于服务端可能使用滚动窗口,刷新后百分比不一定立即变成 0%,可能是逐步下降。 - Codex OAuth 运行时状态也会在其它 Chord 进程更新
auth.state.json后自动重新加载,因此额度快照、reset 计时、账号元数据和账号状态变化无需重启当前会话也应能生效。 - 如果 RATE LIMIT 面板长期不更新,可打开
log_level: debug,在chord.log中搜索responses codex ws: rate_limits event ...(收到事件)或responses codex ws: rate_limits event ignored ...(事件未识别/解析失败)。
TUI 启动了但无法正常请求
Section titled “TUI 启动了但无法正常请求”检查:
- 当前 provider / model 是否存在
- 网络是否能访问对应 API
- 代理配置是否生效
例如:
curl -I https://api.anthropic.comcurl -I https://api.openai.com/v1OpenAI 兼容网关的 400 与超时
Section titled “OpenAI 兼容网关的 400 与超时”遵循官方 API 错误语义的端点请设置 trust_http_400: true,Chord 会把 HTTP 400 视为终止性请求错误。Retry-After 头始终作为 key 冷却时长生效,并优先于任何已配置的重试节奏;retry_after_max_s 限制最长采纳的等待时间(第三方网关默认 60 秒,preset: codex 默认 86400 秒)。聚合或代理网关可能把上游故障包装成 HTTP 400;这类端点可设置 trust_http_400: false 或省略该字段,让未知 400 进入正常的重试和备用模型流程。
如果请求长时间停在 connecting 后重试,请直接测试端点、检查代理设置并查看错误面板。Chord 会限制连接等待时间,避免单个不可用密钥或网关无限阻塞。
DeepSeek / OpenAI 兼容 thinking 模式 400
Section titled “DeepSeek / OpenAI 兼容 thinking 模式 400”如果你使用的是 DeepSeek 这类 chat-completions provider,并看到下面这类报错:
The reasoning_content in the thinking mode must be passed back to the API.Invalid assistant message: content or tool_calls must be set
通常说明这个 provider 要求把上一轮工具调用里的 thinking/reasoning 内容按严格的 assistant message 形状一并带回后续请求。如果同一类报错持续重复,请保留对应的 session dump / trace 供排查。
请在受影响的 model 或 provider 上启用
compat.reasoning_continuity.mode: openai_visible。该选项会回放
assistant reasoning_content,并把其他 wire family 的可移植可见 reasoning
映射为 reasoning_content;provider 专属思考字段应通过
compat.request_overrides.body 添加。
第三方 OpenAI 兼容网关继续使用配置中的原 endpoint。Chord 不会把请求
重定向到 DeepSeek 官方 /beta endpoint,也不会假设网关实现了 Chat Prefix
Completion。若模型在输出可见正文前耗尽预算,且已启用
openai_visible、model 没有变化,Chord 会在同一 endpoint 上用累计的
reasoning_content 做一次有上限的 request-only 回放。网关拒绝这种消息形状
时,Chord 会移除临时回放,继续使用普通恢复提示。这只是尽力而为;网关不
消费 reasoning 回放时,应提高模型输出上限,或把任务拆成更小的请求。
GLM Preserved Thinking 的 body override 需要包含 thinking.type: enabled 和
thinking.clear_thinking: false,并设置
reasoning_continuity.reasoning_replay: all,让 Chord 在回放历史中保留
已完成轮次的 reasoning。DeepSeek 的 Chat 与 Messages 路由会自动完整回传
历史 reasoning_content:请求带 tools 却缺少它时,DeepSeek 会返回 400。
哪些模型 ID 会被当作 DeepSeek 见
DeepSeek 的思考与历史回放。第三方路由的
模型 ID 符合规则、后端却不是 DeepSeek 时,用 reasoning_continuity.contract: none
退出;名字不在规则内的 DeepSeek 路由,用 reasoning_continuity.contract: deepseek
显式开启。两种情况下,回放的
reasoning_content 都必须保持完整、未修改且顺序不变。
Anthropic 还会把每个 thinking 块绑定到生成它的对话前缀,所以压缩或恢复
会话等历史改写可能让原本完好的块被拒,报
Invalid \signature` in `thinking` block. The block is bound to a
different conversation.`。Chord 能识别这类拒绝,并自动丢弃 thinking 块重试
一次,通常无需手动处理;重试会保留正文和已完成的工具事实。如果错误反复
出现,请导出诊断包,并在反馈中附上会话 ID。
Codex WebSocket 400 「No tool call found for function call output」
Section titled “Codex WebSocket 400 「No tool call found for function call output」”这类 WebSocket 会话状态不一致通常会由 Chord 使用本地完整对话自动重试恢复。如果错误反复出现,请导出诊断包,并在反馈中附上会话 ID。
Cache R 百分比明显偏低
Section titled “Cache R 百分比明显偏低”现象:信息面板的缓存读取百分比在 50% 左右(或其他远低于实际命中率的值),但请求体在轮次之间几乎没变,命中率本应接近 100%。
排查步骤:
- 该百分比 = cache-read token 数 ÷ 完整输入侧(未缓存 + cache-read + cache-write)。它只看输入侧,输出量不会稀释它。
- Chord 按协议假设 usage 字段语义:
messagesprovider 的input_tokens是未缓存输入,缓存桶单独上报;chat-completions/responsesprovider 的input_tokens已包含缓存命中部分。 - 兼容网关可能在暴露
messages端点的同时,按另一套协议语义上报 usage,常见的是input_tokens为包含缓存命中的总输入,cache_read_input_tokens只是其中的命中子集。Chord 于是把 cache-read 重复计了一次,显示出来的百分比大约被砍半。 - 要确认,可查看该会话的 LLM dump,再对照网关 usage 文档,或用相同请求的 token counting 结果核验原始字段。若文档或对照结果能确认
input_tokens是完整输入,而cache_read_input_tokens只是其中一部分,再给该 provider 设置compat.usage.input_includes_cache_read: true(见配置)。仅凭两个字段的大小关系不足以判断语义。
已写入的 usage 记录是 append-only 的,改配置后不会被重算;只有新请求会按修正后的语义统计。
MCP 一直未就绪
Section titled “MCP 一直未就绪”先确认:
- MCP 地址是否可访问
- 配置名称是否正确
- 本地模式下是否仅是异步初始化尚未完成
启动后短暂显示灰色的 pending 状态不一定是错误。
会话空闲一段时间后,LSP / MCP 行变成灰色
Section titled “会话空闲一段时间后,LSP / MCP 行变成灰色”如果右侧环境面板里的 LSP 或 MCP 行在 agent 空闲一段时间后变成灰色,这不一定表示集成坏了。
Chord 会在会话空闲时主动卸载空闲的 LSP / MCP 运行时资源,以降低后台占用。处于这种状态时:
- 行会显示为灰色的 idle 状态,而不是错误色;
- 这表示资源是因空闲而被主动卸载,不是连接或配置一定出错;
- 下一次真实请求 / busy 周期开始前,Chord 会先恢复这些运行时依赖,再重建请求面。
只有当该行持续显示红色、明确给出连接/配置错误,或下一次请求时仍恢复失败,才应把它当作故障排查。
写文件后没有诊断
Section titled “写文件后没有诊断”已配置 LSP 但写文件后没有看到诊断:
- 检查本机是否安装了对应语言服务器
- 检查
lsp配置格式是否正确 - 确认目标文件类型与
file_types是否匹配 - 检查是否通过
diagnostics.enabled: false关闭了工具后诊断 - 如果工具结果里出现
LSP diagnostics unavailable for this edit (<server>[: <detail>]); do not treat this edit as verified.,说明 Chord 没能拿到诊断:括号里的 server 未启动、仍在启动、或已退出正在重启,或者等待窗口内没有任何 server 发布诊断(冷启动等待更长,此时括号里是language server: no diagnostics within …)。原因见括号里的细节或日志。启动失败和退出每个 server 每会话最多提示一行,等待超时每会话最多提示一行;仍在启动的 server 在就绪前每次编辑都会提示。
文件同步通知失败时,Chord 会说明诊断不可用并跳过等待,不把旧诊断当成本次验证结果。确认连接断开后,会移除对应服务器实例及无其他实例提供的旧诊断,下一次写文件时会重新启动服务器。取消请求或普通协议错误本身不会被判定为断连。
Go 的 No packages found for open file 可能是包加载失败的后果,应先检查 LSP 日志,而不是修改模块路径。如果日志出现 too many open files,且配置了 lsp.gopls.options.gopls.fileWatcher,删掉这项让 gopls 回到默认的 off,再重启受影响的会话。macOS 上对大型工作区使用 fsnotify 可能耗尽文件描述符,poll 同样会遍历工作区里的每个目录。文件编辑成功不代表 LSP 已完成诊断。
Python 还需要注意:
- 小文件使用
diagnostics.python.semantic_backend,通常是lsp.pyright。请确认diagnostics.python.semantic_backend.server与lsp下的 server key 一致。 - 大 Python 文件在
PATH中能找到ruff时使用 Ruff quick diagnostics。 - 如果大 Python 文件提示因为 Ruff 不可用而跳过诊断,可以安装 Ruff,或设置
diagnostics.python.large_file.run_semantic_when_quick_unavailable: true,强制大文件也运行 Pyright。 - Ruff quick diagnostics 不更新 LSP 侧边栏,只出现在
edit、apply_patch或write工具结果中,并会明确提示完整 Python 语义诊断已跳过。
推荐 Python 配置骨架:
lsp: pyright: command: pyright-langserver args: ["--stdio"] file_types: [".py", ".pyi"]
diagnostics: python: quick_backend: type: command command: ruff完整推荐配置见 配置:工具后诊断。
会话恢复异常
Section titled “会话恢复异常”--continue 或 --resume 没按预期工作:
- 确认当前目录与原会话是否属于同一项目
- 尝试显式使用
--resume <session-id> - 检查是否只是恢复过程较慢而非真的丢失
Chord 会在恢复前自动修复进程中断造成的不完整轮次。如果恢复后的模型 / 服务商状态或对话顺序异常,请使用当前版本导出诊断包,并附上会话 ID。
结果没来得及保存的工具,修复后的卡片会标出两种状态之一:
- 未启动:工具在中断前还没有开始执行,不可能产生副作用,重新核对前置条件后可以重试。
- 结果未知:工具已经开始执行,副作用可能部分或全部发生,先核对当前文件或远端状态,再决定是否重试。
Chord 会在运行工具前先把对应的工具调用消息写盘,因此中断后不会出现「副作用已经发生、但 Chord 不知道当时要执行这个工具」的情况。如果会话目录写不进去(例如磁盘满了),Chord 会暂停工具执行,避免产生无法恢复的重复副作用;状态卡会说明原因,写入恢复后工具会自动继续可用。
委派的 SubAgent 看似卡住,或 escalate 卡片一直执行
Section titled “委派的 SubAgent 看似卡住,或 escalate 卡片一直执行”下面两类故障会导致委派的 SubAgent 看似卡住,Chord 都会自动恢复:
如果恢复会话后聚焦 SubAgent,右侧 MODEL 或 Pool 为空,Chord 会先读取任务、recovery snapshot 和 usage ledger 中保存的模型;记录里没有模型数据时,会按最新 Agent 配置解析。因此不需要手动编辑 subagents/tasks.json 或 meta 文件。
恢复时,durable task_id 是委派工作的稳定身份;explorer-4、explorer-6 之类的 agent_id 只是该任务历次 runtime instance。历史 instance 的 transcript 会按 task 合并,但 sidebar 和焦点路由只暴露该 task 的 canonical 最新实例。不要把旧 agent_id 当作另一项独立任务,也不要通过手工复制/删除 instance 文件改变恢复结果。
如果切换到大型 SubAgent transcript,或在 parked SubAgent 视图按 Enter 继续后整个 TUI 不再响应,Chord 只加载有界 transcript 窗口,其余内容在后台继续加载。工作区共享 skill catalog,但 MainAgent 与每个 SubAgent 会按各自最新权限过滤可见项,并分别记录 invoked 状态。
进程 stderr 直接写入 rotating log 文件,因此即使出现 runtime fatal,完整堆栈也会写入 chord.log 并让进程退出,不会表现为所有按键(包括 raw-mode Ctrl+C)都失效的永久卡死。若 TUI 卡死,先从另一个终端终止对应进程并用 reset 恢复原终端,然后导出 diagnostics。
- Parked SubAgent 恢复后,排队输入会唤醒它;如果 worker 保持
running却没有创建 turn,Chord 会自动重试一次唤醒。 - 如果 worker 仍无法启动,或者 provider / 模型重试最终失败,Chord 会把任务标记为 failed、记录
risk_alert,并唤醒 owner/MainAgent,由其重试、重新委派或报告 blocker;系统不会伪造成功的complete结果。
escalate 是本地协调事件,不是长时间运行的网络操作。如果恢复后一个已经完成的卡片看起来仍是 pending,Chord 会在相邻消息具有相同 tool_call_id 时做严格的局部修复;无法匹配的 orphan result 会被丢弃。
如果恢复后的会话仍然卡住:
- 用当前 Chord 通过
--resume <session-id>重启; - 重试或定向通知委派任务时使用稳定的
task_id,不要使用旧 runtime 的agent_id; - 不要手工编辑
agents/*.jsonl、subagents/tasks.json或 mailbox 文件; - 开启
log_level: debug后,在chord.log中搜索startup watchdog retrying wake、SubAgent failed或removed orphan tool messages。
正常的响应后 watchdog 可能提醒仍存活的 worker 调用 complete 或 escalate。无法恢复的 worker 则会以 failed 终态关闭并路由回 owner;失败不会被当作成功完成。
查看日志 / dump / shell 输出时,TUI 卡片出现异色、背景泄漏或换行错乱
Section titled “查看日志 / dump / shell 输出时,TUI 卡片出现异色、背景泄漏或换行错乱”查看诊断 dump、原始命令输出或其他外部文本时,工具卡片、本地 shell 结果、问题对话框或确认摘要出现异常颜色、背景泄漏或换行错乱:
- 重新执行同样的
read、shell、web_fetch或本地 shell 操作 - 如果仍能复现,同时保留原始文件/输出和截图
Chord 会在渲染前清洗 assistant/thinking 流式回复、工具结果、本地 shell 结果、状态/错误卡片,以及 apply_patch 补丁预览这类工具请求预览,转成终端安全的纯文本。\x1b[1;1H 这类光标控制序列以及其他控制字符、ANSI 转义都会显示为字面量,不会影响卡片布局或背景色。补丁预览里夹带的裸回车符按同样规则处理:CRLF 仍显示为正常换行,单独的 CR 显示为字面量 \r,预览不会在行中折行,卡片背景或左侧边缘也不会被截断或弄脏。如果同一段内容持续导致布局错乱,请同时附上原始文本和截图,以便复现渲染问题。
卡片右缘出现深色竖条,或 emoji 后面的文字位置偏移
Section titled “卡片右缘出现深色竖条,或 emoji 后面的文字位置偏移”如果卡片右缘出现一列深的色块,或者 emoji 后面的文字整体偏左了一点,说明终端和 Chord 对这个 emoji 占几列的认识不一致。emoji 的单元格宽度没有权威标准:同一个 emoji 序列在主流终端上能画出 1 到 6 列不等,1️⃣ 这样的 keycap emoji 按规范算 2 列,很多终端实际只画 1 列。
Chord 按 Unicode 规范宽度计量文本,并在渲染端做了补偿:只要某一行卡片包含宽字符,就用「擦除到行尾」序列重画整行,卡片背景因此总能铺到真实的行尾,不受终端少画一列的影响。
已知的残留问题在应用层无解:
- 计量不准的 emoji 后面的文字在行内会有偏移;
- 终端把 emoji 画得比计量值更宽时,该行可能有一列残留旧内容,直到这一行下次重画;
- 终端擦除时不保留当前背景色、而是填默认背景的情况下,擦除区域只能显示默认背景。
这些都只影响显示:会话内容、回滚翻阅的文本、复制出来的内容都不受影响。想检查你的终端对宽度规范的遵循程度,可以跑一下 ucs-detect。反馈这类显示问题时,请附上截图和终端名称、版本号。
输出触发 TUI 渲染 panic / 进程被 killed
Section titled “输出触发 TUI 渲染 panic / 进程被 killed”如果外层只显示:
Error: program was killed: program experienced a panic并且当前会话需要重新 --resume 才能继续,先查看 ~/.local/state/chord/logs/chord.log 末尾的 Go panic 栈。main.jsonl 通常不会保存这句 panic,因为它发生在 TUI 渲染层,而不是作为会话消息写入。
如果栈里出现以下路径,优先按 TUI markdown/ANSI 渲染问题处理,不要直接归因到模型或工具本身:
github.com/charmbracelet/x/ansi.(*Parser).Advancecharm.land/lipgloss/v2.(*WrapWriter).Writecharm.land/glamour/v2/ansi.(*HeadingElement).Finishgithub.com/keakon/chord/internal/tui.renderMarkdownContent排查 dump 时注意:
- 如果崩溃前最后一个 shell/tool 结果已经写入
main.jsonl,通常说明该工具输出没有丢。 - 如果崩溃时正在等待 LLM SSE 流,
dumps/llm/*.json里可能只有request_body、部分sse_chunks和reading SSE stream: context canceled,表示该次 LLM 响应只 dump 到中途,没有完整 final text。 context canceled多数是进程关闭后的结果,不一定是根因。
反馈问题时,请附上 panic 栈、诊断包、终端名称与版本,以及当时正在渲染的内容。
切换 tab 或重新获焦后画面错乱
Section titled “切换 tab 或重新获焦后画面错乱”切换 tab、切回终端窗口或重新获得焦点后,TUI 偶发出现旧行残留、横线伪影或工具卡片局部错位:
- 画面已错乱时,轻微调整终端窗口尺寸或切走再切回,通常可强制触发一次完整重绘
- 如果仍能复现,同时保留 diagnostics bundle 和截图
如果现象主要发生在获焦后的流式输出过程中,请同时保留 diagnostics bundle 和截图,方便维护者对比 Chord 最近渲染的 frame 与终端实际可见输出。
补充:画面错乱时看到类似 ;250m pyright 的残片,通常不是 LSP 内容,而是被截断的终端控制序列(ANSI/OSC)尾部字符。
重复分隔线 / 旧边框残留
Section titled “重复分隔线 / 旧边框残留”如果主要现象是横线重复、输入区或状态栏分隔线重复、旧卡片边框残留,或右侧栏旧边框残留:
- 先截图,不要先调整窗口尺寸。截图应包含完整终端窗口,尤其是输入区、状态栏和右侧栏。
- 立即导出 diagnostics bundle(
Ctrl+G),尽量在 resize 之前完成,bundle 记录了 Chord 最近渲染的 frame,维护者据此能区分是 Chord 画出的重复线还是终端残留伪影。 - 把两者连同终端名称和版本一起附在反馈里。
两个本地观察也有助于缩小范围:
- 把终端宽度缩小一两列后这条线就消失的话,请在反馈里说明:这指向右边界 wrap 行为。
- 伪影出现在图片预览、粘贴图片或导出 diagnostics 之后的话,也请说明。
长会话里转录区底部内容滚不到
Section titled “长会话里转录区底部内容滚不到”看到最后几行转录内容像被裁掉、最后一个卡片几乎贴着输入分隔线,或已经滚到底但最新对话仍有一部分不可见:
- 留意问题是否出现在长会话中的后台任务结束或状态卡更新之后
- 如果仍能复现,同时保留截图和日志,便于比对转录状态与底部渲染结果
文件编辑工具提示文件在观察后发生变化
Section titled “文件编辑工具提示文件在观察后发生变化”这个警告表示文件在 Agent 上次读取后发生了变化。Chord 会基于当前内容验证编辑;write 和 delete 继续执行前还可能创建备份。
常见原因:
- 你在
read与edit之间用编辑器/格式化器等外部进程改动了文件; - 另一个 Agent 或 Chord 进程改动了文件;
- 格式化器、代码生成器或构建步骤改动了文件。
重试前请重新 read。Chord 成功创建备份时,工具结果会给出它在当前会话目录下的路径,并标明对应的源文件,模型和用户看到的是同一段文本。备份是尽力而为:失败时编辑照常进行,不会有任何内容声称存在备份,只有本地日志记录原因。edit 和 apply_patch 的匹配行为详见编辑工具。
apply_patch 报 hunk not found
Section titled “apply_patch 报 hunk not found”apply_patch 按行匹配 hunk:先做精确上下文匹配,随后是一个独立的标点/空白容错步骤,且只有容错匹配恰好落在一个位置才应用;命中多个位置时会被拒绝并列出歧义行号,而不是静默取第一个。重复块仍需要足够的邻近上下文,让目标位置明确。
看到这个错误时:
- 重新
read目标文件,并基于最新内容重建 patch; - 从最新
read输出中重新复制目标块,并确认 context/removal 行缩进与当前文件一致;如果 hunk 来自旧的带编号输出,先移除复制进来的行号前缀; - 同样的代码块在文件中重复出现时,在
@@hunk 中加入附近未变化的行、使用@@ header锚点,或用*** End of File钉住文件末尾的修改,让目标位置无歧义; - 把过大的 patch 拆成更小的补丁或更小的 hunk;
- 不要通过
shell执行外部apply_patch;请使用 Chord 原生apply_patch工具,这样权限、stale tracking、diff、LSP 和回滚才会保持接入。
感觉滚屏、流式输出或大消息渲染明显变慢:
- 先缩小当前会话上下文规模(
/compact,或为无关工作另开新会话) - 尝试在不同终端中对比
渲染与流式输出的优化原理、以及如何采集 CPU profile 用于反馈,见性能。
上下文压缩不触发 / 触发过频繁
Section titled “上下文压缩不触发 / 触发过频繁”现象:上下文使用率很高但一直没有压缩;或相反,频繁压缩影响使用体验。
排查步骤:
- 确认
context.compaction.threshold是否已设置且大于 0(0 表示关闭自动压缩)。 - 检查 TUI 底部栏或信息面板的
Context百分比。它按可用输入预算计算,不是按总窗口大小,所以可能比预期的低(详见 上下文管理:上下文压缩)。 - 如果设置了
context.compaction.reserved,由于会先扣除预留再应用threshold,自动压缩会在更低的绝对 token 数触发;若压缩过于频繁,可检查 reserved 是否设得过大。 /compact --no会临时关闭当前会话的自动压缩;重新启动会话或执行/compact可恢复。- 如果网关返回缺失或为 0 的用量数据,请开启
log_level: debug,并在自动压缩日志中查看estimated_input_tokens和effective_input_tokens。
注意:loop 模式既不会改变自动压缩,也不会改变请求级上下文剪裁,两者都保持启用。
上下文剪裁误裁重要内容
Section titled “上下文剪裁误裁重要内容”现象:模型似乎「忘了」之前的工具输出,但会话文件里内容还在。
排查步骤:
- 这是上下文剪裁(Reduction)的正常行为:每次 LLM 请求前,过时的工具输出会被从 prompt 中剪裁,但不会修改磁盘上的会话文件。
- 如果你经常需要回头参考较早的读取/搜索结果,可调高
read_like_age_turns和read_like_output_bytes。 - 如果构建 / 测试日志仍然是重要上下文,可调高
shell_success_bytes。 - 如果希望更保守的剪裁行为,整体调高各
*_age_turns和*_bytes参数。
详见 上下文管理:上下文剪裁。
请求被拒绝:context length / input too large
Section titled “请求被拒绝:context length / input too large”现象:provider 返回类似「context length exceeded」或「input too large」的错误。
排查步骤:
- 确认模型
limit.input和limit.context配置正确。如果 provider 公布了单独的输入上限,必须同时配置limit.input。 - 检查
context.compaction.threshold是否过高导致自动压缩触发偏晚。 - 增大
context.compaction.reserved可提前触发压缩,避免请求被拒。 - 如果频繁出现,可使用
/compact立即手动压缩,或降低threshold提前触发自动压缩。 - 在
log_level: debug的日志中搜索oversize,确认是否触发了 oversize recovery(压缩后再重试)。如果自动压缩已关闭,Chord 会停止并报告实际尝试过的所有候选模型都超过当前上下文,而不是无限重试。
OAuth 账号池很大时启动慢
Section titled “OAuth 账号池很大时启动慢”auth.yaml 中包含数百或数千个 OpenAI / ChatGPT OAuth 账号时,Chord 会在后台加载凭据元数据。仅缺少元数据不应阻止启动。
- 个人 Plus/Pro 账号可能只有
user_id,没有chatgpt_account_id。这类账号仍可用于普通请求,但不会发送ChatGPT-Account-ID,也不会参与依赖 account id 的 Codex usage / rate-limit polling。 - 若日志显示
account_user_id mismatch或account_id mismatch,说明配置里显式写出的身份和 token 自身能解析出的身份冲突;这类应修正或移除对应 credential。
手动转换 Codex/sub2api 导出的账号时,请保留能获取到的 email、account_id 和 account_user_id。需要逐项诊断时,运行 chord doctor models。
后台 job 的进程还在跑,但 job_list 里看不到
Section titled “后台 job 的进程还在跑,但 job_list 里看不到”症状:ps 能看到某个 job 命令起出来的进程,但 job_list 显示没有活跃 job。
排查顺序:
- job 可能已经结束了。
job_list默认只列正在运行和正在停止的 job,要看保留的终态 job 得传include_finished: true,或者直接看这个 job 的完成卡片。 - 进程可能已经脱离了这个 job 的进程组。job 管的是命令启动的整个进程组,留在组里的子进程会让 job 保持活跃;而调用
setsid、setpgid的进程(会自我 daemon 化的工具,或包装层主动 detach)已经在 job 之外,不再受这个 job 的截止时间、job_kill或会话清理约束,需要你自己停掉。 - 直接写
命令 &或nohup 命令 &不会脱组,因此不会自行逃逸;只有显式脱离进程组才会。Chord 不会为逃逸的进程扫描进程树。 - 停止这个 job 时可能没能向进程组发信号。命令退出之后,只有当命令退出那一刻记录到的某个成员仍在这个组里时,Chord 才会向该进程组发信号;主动离组的成员不算数。没有这份依据时,停止会按「未能确认」报告,命令留下的进程则继续运行。可在日志里搜
no member witness或no recorded member is still in the group,并自己停掉这些进程。
何时检查日志
Section titled “何时检查日志”遇到以下问题时,优先查看日志:
- provider 请求失败但终端只显示摘要错误
- 上下文压缩未触发 / 上下文超限
- MCP / LSP 初始化异常
- hook 执行结果与预期不符
- headless 集成事件不完整
默认日志目录:${XDG_STATE_HOME:-~/.local/state}/chord/logs/。当前日志文件为 chord.log,轮转文件为 chord.log.1 和 chord.log.2。
可通过 --logs-dir <path> 或环境变量 CHORD_LOGS_DIR=<path> 覆盖。快速复现并收集日志:
chord --logs-dir ./chord-logs