DeepSeek Harness 会话日志报 seq gap 打不开?双开进程与中断重试排查
DeepSeek Harness 会话报 Error: corrupt session log: seq gap in committed region 打不开,根因几乎都是两个进程同时打开同一个 DSH_HOME 在并发写会话日志——最常见的就是桌面端和 Web 端一起开着。 中断工具调用后重试会放大这种碰撞。先备份数据、只留一个实例,再把损坏的会话导出留底。
DeepSeek Harness 会话日志 seq gap 报错长什么样
报错格式固定:corrupt session log: seq gap in committed region at line N (expected X, got Y),随后这个会话彻底打不开。 有用户实跑遇到(讨论原文),现象如下:
- 打开某个旧会话,加载即报
seq gap in committed region at line 1649 (expected 5259, got 5255); - 会话列表里这个会话无法打开,其余会话正常;
- 对照日志内容,能看到同一段 seq 被写了两遍:先是崩溃恢复合成的占位事件(
tool/result isError=true→step/end→turn/end→session/end-seed),随后同一工具调用的真实结果又复用了相同的 seq 从头写了一遍。
用户最初以为是「中断工具调用后重试复用旧 seq」,但被标记为答案的回复指出真相:单看日志像重试,实际是两个进程在写——一个进程恢复会话并提交了合成关闭事件,另一个还活着的进程用自己的内存游标继续提交同一个工具调用的真实结果。JSONL 后端对跨进程写入没有任何协调,两批都"通过"了各自的校验,于是写进了重叠的 seq(来源)。
DSH 会话 seq gap 根因:桌面端与 Web 端双开并发写
触发条件有两个,叠加后几乎必现:同一个 DSH_HOME 同时被两个实例打开,且期间有中断的工具调用。 拆开看:
- 双开是必要条件:在一个图形会话里再启动一个
dsh web桌面包装实例,两个进程指向同一个DSH_HOME; - 中断放大碰撞:工具调用(如
bash跑sleep 30)执行到一半被取消/停止,崩溃恢复路径会合成并持久化一批关闭事件; - 无跨进程协调:JSONL 后端只校验自己内存里的游标(
appendCore检查event.seq === state.cursor + i),两个进程各写各的,重叠 seq 就这么产生了; - 会话子系统文档其实早已点名这个缺口:容忍并发写者需要日志之外的信号(来源)。
这也解释了为什么这个问题"难主动复现、又突然可复现"——它需要两个实例同时活着。
DSH 会话打不开怎么恢复:备份、开新会话与避免双开
恢复三步走:先备份,再只留一个实例,最后开新会话继续。 不推荐手工改日志文件。
- 立即停止所有 DeepSeek Harness 实例:关掉桌面端和浏览器里的
dsh web(Ctrl+C),避免继续并发写入; - 核对版本与进程,确认双开就是写入源:执行
dsh --version看版本,再用进程列表确认有几个实例挂着同一个DSH_HOME(macOS/Linux):
dsh --version
ps aux | grep -E 'dsh|deepseek' | grep -v grep
Windows 换成 tasklist | findstr /i dsh。超过一个实例在跑,就是并发写入的源头;
- 备份损坏会话的数据:找到会话文件(
~/.dsh/profiles/<name>/sessions/下的session.jsonl.zstd),复制一份到别处留底:
ls -lh ~/.dsh/profiles/<name>/sessions/
cp ~/.dsh/profiles/<name>/sessions/<会话文件>.jsonl.zstd /tmp/dsh-session-backup/
- 重新启动一个实例(建议桌面端或
dsh web二选一),在会话列表里确认旧会话仍无法打开属预期——它已被判定为损坏; - 开新会话继续工作,把损坏会话里的重要对话内容手工搬到新会话;
- 后续使用时坚持单实例:不要桌面端 + Web 端同时挂同一个
DSH_HOME,有中断习惯的话更要注意。
seq gap 修复进度:DeepSeek Harness 跨进程写锁补丁等官方合入
社区已在 #4662 给出完整重建与补丁分支:用跨进程写锁序列化追加,游标过期的进程直接拒绝而不是写重叠 seq。 要点:
- 追加时先拿跨进程写锁,持锁期间要求本批次延续持久化的尾部;
- 游标落后于持久化尾部的进程,直接报诊断并拒绝写入(reject-never-repair:游标过期就该恢复会话,而不是补丁文件);
- 评论者已实际运行该分支,并附了尾部读取的性能修复审查意见(来源);
- 在官方合入前,按本文「单实例 + 备份」的做法即可绕开。
注意事项
- 报错信息里行号和 seq 每次不同,是并发写入的产物,不是数据丢失——对话内容大概率还在,只是日志无法回放。
- 不要手工改
session.jsonl.zstd的 seq:还要同步改 surface 引用与 token 投影,一步错会连锁损坏。 - 同类会话问题还汇总在《DeepSeek Harness 插件报错合集:DSH plugin 不加载、Web UI 异常与会话缓存修复》里,可对照查看。
常见问题
根因是两个进程同时打开同一个 DSH_HOME 并发写会话日志:桌面端与 Web 端(dsh web)各用自己内存里的游标追加,JSONL 后端没有跨进程协调,写出的 seq 重叠,加载时即报 seq gap in committed region(来源)。
中断时一个进程会合成一批关闭事件(tool/result isError=true → step/end → turn/end → session/end-seed)写入日志,另一个还活着的进程继续用自己的旧游标写同一工具调用的真实结果,两批事件 seq 重叠、随后回退,日志损坏几乎必然发生。
先备份会话文件(~/.dsh/profiles/<name>/sessions/ 下的 session.jsonl.zstd)留底,用 ps aux(Windows 用 tasklist)确认没有双开,只保留桌面端或 dsh web 一个进程,再开新会话继续。手工改 seq 需要连 surface 引用一起改,风险很高,不建议普通用户操作。
讨论 #4662 已出跨进程写锁补丁分支:追加时加锁并要求批次延续持久化尾部,游标过期的进程直接拒绝并给出诊断,而不是写出重叠 seq(来源)。等待官方合入后,更新到 dsh --version 含补丁的版本即可。
来源
- deepseek-harness Discussion #4598:中断工具调用后重试会复用旧 seq,导致会话日志损坏无法打开· deepseek-ai(GitHub Discussions)
- deepseek-harness Discussion #4662(同一 bug 的更完整重建与补丁分支)· deepseek-ai(GitHub Discussions)