在 AI DevSpace 里修一个 Bug:跟着报错信息一步步定位根因
今晚我在 AI DevSpace 体验版里只想做一件很小的事:让 AI Shell 写一个 average.py,算一组分数的平均分,对 [88, 92, 79] 和空列表 [] 各求一次平均,再运行给我看。没想到这件五分钟的事花了更久——而真正值得写的,恰恰是多花的这段时间。
第一步:一切正常,只是文件“不见了”
AI Shell 先加载了写代码的 skill,接着检查 CodeArts ACP 服务是否健康:用 curl 调用本地的健康检查接口(19300 端口),返回 ok。随后它拿到了沙箱路径 /root/job-envs/sandboxes/codearts-1794225313,在里面建了 average-project 目录,创建会话并把写代码的 prompt 发了出去。日志里显示会话已经建立,CodeArts 也“报告”文件写好了。
但当 AI 用 cat 去读 average.py 时,终端只回了一行:No such file or directory。find 全目录搜了一遍,什么都没有;ls 一看,目录是空的。工具说成功了,磁盘说没有——这是今晚第一个真正的报错,也是最容易被忽略的一种:没有报错信息的“成功”。
第二步:别急着重做,先读报错
遇到这种情况,最省时间的办法不是立刻再跑一次,而是把已经看到的信息排个队:服务健康检查是 ok 的,说明 ACP 本身没死;会话创建成功,说明连接没断;文件不在预期位置,说明问题不在“写没写”,而在“写到哪儿了”。
AI 顺着这条线往下查:读了沙箱注册表,发现 CodeArts 沙箱用的是 bwrap 隔离;用 nsenter 进到沙箱的命名空间里再找,依然没有 average.py。文件既不在宿主机上,也不在沙箱内部——它根本就没有落盘。
第三步:根因是一条路径
真正的原因,藏在传给 acpx 的 cwd 里。创建会话时传的是宿主机路径 /root/job-envs/sandboxes/codearts-1794225313/average-project,而沙箱内部看到的却是 /workspace。两边各有一套“正确”的路径,拼接起来就对不上号:CodeArts 在它以为正确的位置写了文件,宿主机在另一个位置找文件,结果就是“写成功了,但谁也找不到”。
定位到这一步,修复就很直接了:用沙箱内部路径 /workspace/average-project 重新创建会话,再发一次同样的 prompt。这一次,文件出现在宿主机上,cat 读到了完整内容:
def average(scores):
if not scores:
return 0
return sum(scores) / len(scores)
if __name__ == "__main__":
print(average([88, 92, 79]))
print(average([]))
把它复制到 /root/workspace/average.py 再运行,输出是 86.33333333333333 和 0。[88, 92, 79] 的平均值是 259 ÷ 3 ≈ 86.33,空列表安全返回 0,没有触发 ZeroDivisionError——AI 生成的代码里已经写了 if not scores: return 0 这层防护,空列表这个“坑”在写代码时就被填上了。
这次修 Bug 教我的四件事
第一,别只信“成功”,要亲手验证。工具说写好了,cat、ls、find 才是证据。任何没有落盘验证的“已完成”,都只能算“已发送”。
第二,报错信息是坐标,不是判决。No such file or directory 没有告诉我错在哪一行,但它划定了搜索范围:问题在“位置”,不在“内容”。顺着这个范围查注册表和命名空间,比盲目重试快得多。
第三,先怀疑“约定”,再怀疑“代码”。这次的根因不是代码逻辑,而是两边对同一目录的叫法不一致。路径、端口、环境变量这类“约定”出问题时,现象往往是“一切正常,只是什么都没有”。
第四,把复现做小。小任务的好处是每一步都便宜:一个十行的小脚本、一次 cat、一次 find,就能把问题从“玄学”变成“可定位”。如果第一次就把几百行代码一起跑起来,同样的路径错位会藏得更深。
说到底,修 Bug 的过程就是一条很朴素的链:复现、读报错、缩小范围、验证假设、再跑一次。AI 帮我把每一步都跑得更快,但决定查哪一步、信哪一条证据的,仍然是人。今晚这个 Bug 没有改一行业务代码,却让我对“路径”这两个字多了一份敬畏——下次再看到“文件不存在”,我会先问一句:你说的路径,和我说的路径,是同一个吗?
- 点赞
- 收藏
- 关注作者
评论(0)