No conversation found with session ID:Claude Code 在告诉你什么

那个 id 的文件不在 claude --resume 找的地方,而出现这种情况的原因有五种

完整的消息就是一行:

$ claude --resume 7b1d2c3e-1111-4222-8333-444455556666
No conversation found with session ID: 7b1d2c3e-1111-4222-8333-444455556666

Claude Code 把每段对话存成一个文件 <session-id>.jsonl,放在 ~/.claude/projects 下按项目分的目录里。按 id 恢复就是找到那个文件。这个报错说的是它一个都没找到,或者找到的那个里面没有对话。它绝不意味着会话存在 Claude Code 忘了的地方:列表背后没有数据库,只有那些文件。

下面的内容都在 Claude Code 2.1.295 上用一个一次性的 CLAUDE_CONFIG_DIR 复现过。

它不是什么:目录不对

常见的建议是 cd 到会话当初跑的项目里。对按 id 恢复来说,在当前版本上这并不重要:查找会搜 ~/.claude/projects 下的每一个项目目录,测试里一个在某个仓库里开的会话,从另一个仓库按 id 恢复成功了。交互式选择器不一样,也就是不带 id 的 claude --resume:它列出你当前所在目录的会话,所以一个被改名或移动过的项目,它的会话不在列表里,但按 id 仍然有用。

五种原因

  1. 文件被清理了。~/.claude/settings.json 里的 cleanupPeriodDays 默认是 30 天,Claude Code 会删除比这更旧的转录,而且不说一声。上个月笔记里记下的一个 id,是撞上这个报错最常见的方式。清理是怎么工作的。
  2. 文件被删了。可能是手动删的,可能是 claude project purge,也可能是一个删掉旧 .jsonl 文件的清理脚本。
  3. 配置目录不一样。设置了 CLAUDE_CONFIG_DIR 之后,Claude Code 读的是 $CLAUDE_CONFIG_DIR/projects,完全不看 ~/.claude 下的东西。一个 shell、一个容器或者一个 IDE 任务,如果它的设置和当初写会话的那个不同,那么来自另一套目录的每个 id 都会得到这个报错。
  4. 会话是 headless 写的。由 SDK 驱动的客户端和 headless 客户端写出的会话,可能落在 <config>/transcripts/ 而不是 projects/。放在那里的文件 --resume 找不到;测试里它给出的正是这条消息,直到它被移到 projects/ 下。
  5. 文件里没有对话。一个空的 .jsonl,或者只有一个摘要行、没有消息的,即使文件明明白白就在那里,也会给出同样的报错。

差一点的情况会打印别的东西:带 -p 时,短的 id 前缀会被拒绝,提示 --resume requires a valid session ID or session title,因为 claude -p --resume 要的是一个完整的 UUID 或者会话标题,不是前缀。

驱动 Claude Code 的程序,比如 Agent SDK 或者编辑器扩展,底层跑的是同一个 CLI,所以当这条消息作为一个更长报错的一部分出现时,原因和上面是同一套。

找到那个文件

# 它是不是在默认目录下的某处,包括 transcripts/
find ~/.claude -name '<session-id>.jsonl' -ls

# 这个 shell 用的是哪个配置目录
echo "${CLAUDE_CONFIG_DIR:-~/.claude}"

# 某个 id 在另一个文件里被提到,比如子智能体或改过名的副本
grep -rl '<session-id>' ~/.claude 2>/dev/null

如果 find 列出的文件大小是零,或者只有几百字节,那就是第 5 种,没什么可恢复的。如果它在 transcripts/ 下,就把它移进任意一个项目目录,然后按 id 恢复:

mv ~/.claude/transcripts/<session-id>.jsonl ~/.claude/projects/<project-dir>/
claude --resume <session-id>

如果它在另一个配置目录下,就用那个 CLAUDE_CONFIG_DIR 运行 claude --resume,或者把文件复制过去。如果 find 什么都没打印,文件就没了:在清理之前做的时间机器快照或其他快照,是 Claude Code 自己唯一还能用的副本。

让它别再发生

把保留期调长,清理就不会再拿走你还在引用的会话:

# ~/.claude/settings.json
{ "cleanupPeriodDays": 3650 }

这能解决第 1 种原因。对已经没了的会话没用,对其他几种也没用。

文件已经没了的时候

在文件还在时建好的索引,是那次清理之后唯一活下来的副本。deja 会读这台机器上每一个 Claude Code 转录,它读过的会话在 Claude Code 删掉文件之后仍然留在索引里。按内容找到它,再写回 claude --resume 会看的地方:

deja "the migration that broke the staging build"   # 命中里带着会话 id
deja show <id>                                      # 读 deja 留下的那段对话
deja resume <id> --write-back                       # 写回 ~/.claude/projects,并打印恢复命令

写出来的文件里是对话,也就是用户和助手的来回;工具调用及其输出仍然只留在 deja 里。裸 deja 打开的界面里,Deleted 标签列出每一个被智能体删掉、而 deja 还留着的会话,对一个按 R 效果相同。对 deja 从没读过的会话,这些都帮不上忙,所以它得在清理发生之前就位:

curl -fsSL https://raw.githubusercontent.com/vshulcz/deja-vu/main/install.sh | sh
deja install --auto

第一次建索引会读取磁盘上已有的历史,所以它覆盖你现在手上的这些会话。建索引和检索都在本地。

找回被删掉的会话 · 删除 Claude Code 的会话 · 接着昨天的那次会话继续