DSH read_image 图片工具报 cannot get property "fs" without inject?DeepSeek Harness 排查

故障排查发布于 2026-08-27作者: DSH Plugin 插件中心
DeepSeek HarnessDSHread_imagecannot get property fs without inject图片工具报错
DSH 原生 read_image 报 cannot get property "fs" without inject?根因是 @deepseek-ai/dsh-tool-fs 在 attachments 子上下文注册却传收窄 scope,ctx.fs 触发守卫。原生 bug,等官方修复。

DSH 调用原生 read_image 工具立即报 Error: cannot get property "fs" without inject,而 read / write / edit 全部正常——根因是 DSH 原生包 @deepseek-ai/dsh-tool-fs 的一行 scope 传错:apply()read_image 注册在 attachments 门控的子上下文里,却把收窄后的 imageCtx 传给了执行体,执行体按属性访问 ctx.fs 触发 cordis 守卫。 这是 DSH 本体的 bug,装任何插件都不改变它;临时方案是走外部视觉 CLI,正式修复需等官方合入后升级。

read_image 报 cannot get property "fs" without inject 长什么样

报错固定为 Error: cannot get property "fs" without inject,只在调用 read_image 时出现,且与图片文件本身无关。 报告者实跑复现(讨论原文):

  1. 环境:dsh 0.1.0-rc.6、Windows、web profile,freedom preset 复现,凡挂载 @deepseek-ai/dsh-tool-fs 的 preset 理论上都中招(缺陷在包本身);
  2. read / write / edit 正常,唯独 read_image 失败——换任意图片文件都一样;
  3. 这条链上每一步看起来都是健康的:插件挂载成功 → 工具注册成功、出现在模型可见的工具目录里 → 模型看得到它、也会调它 → 直到真正执行那一刻才炸;
  4. 代价是模型白白烧掉一整轮——它不知道这个工具坏了,只知道调用失败了。

根因:注册在收窄子上下文里的 read_image

@deepseek-ai/dsh-tool-fs/lib/index.jsapply() 在 attachments 门控子上下文里注册 read_image,并把那个收窄的上下文传给了执行体。 代码形状如下(来源):

js
const inject = ["tools", "fs", "systemPrompt"]; // 插件级声明
function apply(ctx, config) {
  applyReadTool(ctx);            // 正常:外层 ctx 声明了 fs
  ctx.inject(["attachments"], (imageCtx) => {
    applyReadImageTool(imageCtx); // ← imageCtx 只声明了 "attachments"
  });
  // ...
}

applyReadImageTool 的执行体按属性访问 ctx.fs.readBytes(...)(并经 ctx.tools.register(...) 注册)。Cordis 的守卫对未声明的服务属性访问直接抛错,于是执行死在 cannot get property "fs" without inject。函数自己的注释写明了预期契约——「执行使用其 fs 服务,加上可选的 attachments / llm 服务」——即调用点本应传外层 scope,实际却传了收窄后的访问器。执行体对可选服务其实已经用 ctx.get("attachments") / ctx.get("llm") 做了正确的运行时查找,只有 fstools 这类声明式属性访问受了影响

为什么能通过所有挂载期检查

因为守卫在执行期才响。 这个 bug 的形状值得单独说:插件挂载成功、工具注册成功、模型可见、模型调用——全部正常,直到执行那一下。社区里同一家族还有:

  1. #1782:插件挂载成功(fiberPhase: "active"、构造函数无报错),但它注册的命令和工具对 agent 完全不可见
  2. #2917dsh plugin add exit 0、--dump-config 显示一切正常,然后 harness 完全起不来——因为 --dump-config 只组合、不启动。

共同点:「挂载/组合成功」这个信号,不保证注册的东西真的可用。 而你这条是这一族里症状最良性的一个——cordis 的报错明确点名了缺哪个服务(cannot get property "fs" without inject),在社区里算难得的;同族其它成员大多是静默的。这也是支持「注册期就该校验 scope」这类改进的正面例子。

怎么排查与临时绕行

先确认是不是这个 bug:只有 read_image 崩、兄弟工具全正常,且与图片无关——那就是它。 按步骤确认:

  1. 核对报错形态:调用 read_image 得到 cannot get property "fs" without inject,同一会话里 read / write / edit 均正常;
  2. 确认无关插件:这是 @deepseek-ai/dsh-tool-fs 包内的缺陷,装什么插件都不改变它——不要先怀疑刚装的插件;
  3. 等待官方修复:社区已定位到调用点(src/index.tsimageCtx 传进 applyReadImageTool,而执行体访问 ctx.tools / ctx.fs),升级含修复的 dsh 版本后验证 read_image 直接向模型返回图片;
  4. 临时绕行:把图片读取路由到外部视觉 CLI(如 modlens),绕开 DSH 工具管线——这也是这个 bug 存在一段时间没人报的原因:遇到的人第一反应是绕过去,绕过去就不回来报了。

修复方向:调用点一行改动(面向维护者)

推荐修法是把外层 ctx 传进 applyReadImageTool,而不是扩宽内层 inject。 两条都能过守卫,但语义不同:

  1. 传外层 ctx:声明的是「工具执行依赖 fs / toolsattachments 只是注册时机门」——与函数注释的契约一致,也与执行体已有的 ctx.get("attachments") / ctx.get("llm") 运行时查找写法一致:
js
ctx.inject(["attachments"], () => {
  applyReadImageTool(ctx);
});
  1. 扩宽内层 inject 到 ["attachments", "fs", "tools"]:能用,但表达的意思错了——fs 并不需要等 attachments 就绪;将来有人调整 attachments 的可用条件,这个写法会连带影响 fs 的解析时机。

  2. 回归测试要求:现有生命周期测试只证明 read_image 随 attachment fiber 挂载/销毁出现和消失,schema 可见性没有触发守卫属性访问。回归用例应调用完全组合后的 ToolFs 插件拿到的工具并要求返回成功图片结果,并保留三组配对断言:attachment 挂载 → 工具可见且可执行;attachment 销毁 → 只有 read_image 撤回;重新挂载 → 再次可见且可执行

注意事项

  1. 别把问题归到刚装的插件上——这是 DSH 原生包 dsh-tool-fs 的缺陷,与插件无关。
  2. 模型会在 read_image 上白烧一轮,可提示模型改用其它方式读图(如让用户描述),或直接走外部视觉 CLI。
  3. 排查图片问题时,#4615dsh-llm-pi-ai 把非 png/jpeg/gif 图片原样发给严格 OpenAI 兼容后端)与本文同属「图片路径」一带,两条一起看能省时间。
  4. 同类插件报错还汇总在《DeepSeek Harness 插件报错合集:DSH plugin 不加载、Web UI 异常与会话缓存修复》里。

来源:Discussion #4612#1782#2917

常见问题

DSH 调用 read_image 报 Error: cannot get property "fs" without inject,read/write/edit 却正常,是什么原因?

@deepseek-ai/dsh-tool-fs 的 apply() 把 read_image 注册在 ctx.inject(["attachments"], …) 收窄过的子上下文里,却把这个收窄后的 imageCtx 传给了执行体;执行体按属性访问 ctx.fs / ctx.tools,cordis 的守卫在执行期抛错(来源)。

为什么只有 read_image 失败,read/write/edit 都正常?

read/write/edit 在 apply() 里直接由外层 ctx 注册(声明了 fs),只有 read_image 被包进 attachments 门控子上下文并拿到收窄 scope——执行体用它访问 ctx.fs 时触雷,与图片文件本身无关。

插件挂载正常、工具也能被模型看到,为什么调用才报 cannot get property "fs" without inject?

cordis 的服务属性守卫只在执行期响应:插件挂载成功、工具注册进模型可见目录、模型看到并调用,直到真正执行才炸。挂载/组合成功这个信号不保证注册的东西真的可用,同类问题还有 #1782、#2917。

这个问题怎么解决?装插件有用吗?modlens 是什么?

这是 DSH 原生包的一行 scope 传错,装任何插件都不改变它,只能等官方修复后升级 dsh。临时方案是绕开 DSH 工具管线,把图片读取路由到外部视觉 CLI(如 modlens)。

这个 bug 属于插件问题还是 DSH 本体问题?社区有没有修复补丁?

属于 DSH 本体(@deepseek-ai/dsh-tool-fs 在 DSH 内)。社区已给出调用点一行修复(把外层 ctx 传给 applyReadImageTool),报告者已在 Windows 上验证通过,属良性报错——cordis 明确点名了缺失的服务。

来源