DeepSeek Harness 动图只取首帧与 Android 附件上传失败:read_image 与附件排查
DeepSeek Harness(DSH)的图片与附件有两个特别容易误判的问题,而且方向恰好相反:一个是「信息被丢掉但没人说」——read_image 接受动图,却只把第一帧交给模型,结果里既不提帧数也不做说明,于是模型把动图当静帧描述;另一个是「环境前提不满足但报错很短」——在 Android 应用沙箱这类受限环境里,附件上传必失败**,报 EACCES: permission denied, open '/data/user/0',因为附件持久化目录的同步会一路向上走到文件系统根,而上级目录对普通应用只有执行位、没有读位。** 前者要把它当契约 + 可观测性缺口来处理(「只取首帧」是文档写明了的,缺的是「告知」),后者要按路径边界去绕(换数据目录)或等修法(遇到权限错误就跳过)(#8793、#9247)。
DSH插件 动图只取首帧:丢帧是契约,不告知才是缺陷
一句话结论:read_image 通过文件头嗅探接受动图,但附件归一化会把它重编码成单张静态图,只保留第一帧——帧数在模型看到之前就已经丢了;而结果里既没有帧数也没有文本说明,所以模型把动图当成静帧使用。(#8793)
DSH插件 判据与口径:别把两件事混成一件
这一点很关键,因为它决定了你该反馈什么(#8793):
| 事项 | 性质 | 依据 |
|---|---|---|
| 「动图退化为静态、只保留第一帧」 | 有文档的契约,不算缺陷 | 附件模块说明里明确写了这一行为(#8793) |
| 「模型从未被告知帧数」 | 缺陷,是本次要修的点 | 返回结果里只有图片引用,无文本、无帧数(#8793) |
所以正确的反馈口径是:结果里应当带上原始帧数并在工具描述里说明动图行为,而不是「为什么要丢帧」(#8793)。
DSH插件 三步确认与处置
- 确认判据:让 agent 读一张明显有动作的动图,观察它描述为「一张静态图片」;同时检查工具返回里是否没有任何帧数或说明——两者同时成立即为本条(#8793)。
- 用户侧规避(推荐,最省事):自己先把动图抽帧并拼成一张联系表,再交给
read_image:
# 抽取若干关键帧并横向拼接成一张静态图(示意)
ffmpeg -i anim.gif -vf "fps=1,scale=320:-1,tile=4x3" -frames:v 1 contact-sheet.png
这样模型看到的是一帧里包含多帧信息的图,既保留了动作概览,也避开了「模型以为这是静帧」的误会(#8793)。
DSH插件 Android 受限环境里附件必失败:同步一路走到文件系统根
一句话结论:附件模块为了保证落盘持久性,会从数据目录逐级向上同步直到文件系统根;而在 Android 应用沙箱里,上级目录(如 /data/user/0)对普通应用只有执行位、没有读位,于是以只读方式打开必失败——整个附件写入流程就此中止。 报错是 EACCES: permission denied, open '/data/user/0',而纯文本会话完全正常(#9247)。
DSH插件 判据:两个对照能立刻定性
- 「文本正常、只有附件失败」:说明附件模块这条路径上有额外前提,网络与凭据都正常(#9247)。
- 报错路径是文件系统根或数据目录的上级,而不是你的工作区:这是本条的指纹——如果报错路径就在工作区里,那是另一类权限问题(#9247)。
- 注意这不是 Android 专属:讨论里明确说明该行为在其它同类受限文件系统上也成立(只要上层目录对进程不可读),所以排查思路可以通用(#9247)。
DSH插件 三步处置
- 换数据目录(用户侧规避):把 DSH 的数据目录放到应用自身可读、可写的路径下,避免上级目录不可读的情况(#9247)。
- 修法方向(讨论中给出并实测的补丁):让同步步骤在遇到
EACCES/EPERM时跳过而不是中止;前提是该目录不可写(这一点要保持——否则会削弱持久性保证)(#9247)。 - 验证:重跑同一张图片的附加操作,预期不再报
EACCES,且后续读取附件正常(#9247)。 - 顺带记住:测试期望里包含「哪些目录需要同步」的断言,改动时需同步更新(讨论里提到的连带工作量)(#9247)。
DSH插件 排查注意事项
这一族只有两条,但两条的排查方向完全不同:一条是「信息缺失」,一条是「环境前提」。先看报错有没有,再决定往哪边想。 七条要点:
- 没有报错、只是描述不对 → 往「信息缺失」方向查(动图那条)(#8793)。
- 有
EACCES且路径在文件系统根 → 往「环境前提」方向查(#9247)。 - 「文本正常、附件失败」是极强的范围限定,优先用它(#9247)。
- 动图那条别反馈错方向:契约本身没问题,缺的是「告知」(#8793)。
- 抽帧拼图是最实用的用户侧手段,比等修法快(#8793)。
- 同步跳过的前提是「目录不可写」,不要为了绕过错误而放宽持久性保证(#9247)。
- 修复状态如实:两条在讨论所指版本里都未修;动图那条是「契约内行为 + 可观测性缺口」,附件那条报告者给出的补丁未合入,因此当下只有换目录这类用户侧规避。
排查附件与图片问题时,「环境」这一层往往决定了结论——尤其数据目录放在哪。如果你想先把插件与日志这一层看清,与其在各处手敲命令,不如用 DSH Plugin Hub 这类可视化插件市场:已安装列表、装卸历史与系统日志集中在一个面板里。

常见问题
在 DeepSeek Harness 里模型把动图当静帧,是因为交付给模型的其实是单张静态图。工具会嗅探文件头并接受动图类型,但附件归一化那一步会把它重新编码成单张静态格式,帧数在模型看到之前就已经丢了;而且结果里既没有文本说明、也没有帧数提示,所以模型无从知道这是动图。规避是自己先用 ffmpeg 抽帧并拼成一张联系表再读;最小修法是源文件多于一阵时在结果里带上原始帧数并在工具描述里写一句。
在 DeepSeek Harness 里「只取首帧」本身是有文档的契约,所以这部分不算缺陷;附件模块的说明里明确写了动图会退化为静态、只保留第一帧,真正的问题是模型从未被告知这件事,结果被当成完整信息使用。因此反馈口径应当落在「结果里缺少帧数与说明」,而不是「为什么要丢帧」。
在 DeepSeek Harness 里附件上传必失败,是因为附件的持久化目录校验会从你的数据目录一路向上同步到文件系统根,而上层目录对普通应用只有执行位、没有读位,于是以只读方式打开必然失败。绕开办法是把数据目录换到应用自身可读的路径下;长期修法是让这一步在遇到权限错误时跳过而不是中止(讨论中给出的补丁就是这个方向,前提是该目录不可写)。
在 DeepSeek Harness 里「文本正常、附件失败」说明问题出在附件的占用流程,而不是网络或权限配置整体不可用。附件写入涉及持久化目录的同步与对象落盘,文本消息不走这条路径,所以该差异能把范围缩到附件模块;进一步的判据是看报错里的路径是不是文件系统根或数据目录的上级,而不是你的工作区。
相关术语
- read_image
- read_image 是 DeepSeek Harness 的文件工具之一,用于把图片文件作为图片内容交给模型。它通过文件头嗅探判断类型,再把图片交给附件层归一化与编码,因此交付给模型的形态由附件层决定。— https://github.com/deepseek-ai/deepseek-harness/discussions/8793
- 附件归一化
- 附件归一化是 DeepSeek Harness 在把图片交付给模型前的重编码步骤,用于统一格式与体积。对动图而言这一步会退化为单张静态图,只保留第一帧。— https://github.com/deepseek-ai/deepseek-harness/discussions/8793
- durable home
- durable home 是附件模块用来保证附件落盘持久性的目录,写入后会逐级向上同步以确保元数据落盘。它从数据目录走到文件系统根,因此在受限文件系统上会遇到无法以只读方式打开的上层目录。— https://github.com/deepseek-ai/deepseek-harness/discussions/9247
- EACCES
- EACCES 是 POSIX 的权限拒绝错误码,表示进程没有访问该路径所需的权限。在 DeepSeek Harness 的附件场景里,它常表示某一级上层目录对当前进程不可读。— https://github.com/deepseek-ai/deepseek-harness/discussions/9247
来源
- #8793 — read_image passes only the first frame of an animated GIF, with no notice· deepseek-ai(GitHub Discussions)
- #9247 — attachment-local: durable-home walk reaches the filesystem root — image attachments fail with EACCES· deepseek-ai(GitHub Discussions)