快速结论:该报错通常出现在 Windows 上运行 Dify API 单元测试 test_detect_file_encodings 时:测试代码在 NamedTemporaryFile 仍打开的情况下调用 detect_file_encodings,后者通过 charset_normalizer.from_path 再次打开同一路径,Windows 不允许这样做,于是抛出 PermissionError。优先排查测试文件是否在检测前已关闭临时文件。
适用环境:Issue 已确认:Dify main @ b6824334cf(源码安装,API 1.16.x)、Self Hosted(Source)、Windows;Python 与依赖版本未在 Issue 中给出。Linux/macOS 下该测试通过。
最快修复方案:暂无确认的一步修复方案(Issue 中未合并修复 PR;社区回复确认了诊断并给出建议代码,属于可优先尝试的修改)。
注意事项:这是仅涉及测试的可移植性问题,生产代码 api/core/rag/extractor/helpers.py 无需改动;改为 delete=False 后必须自行清理临时文件,否则会残留 .txt 文件。
问题场景
在 Windows 上以源码方式安装并运行 Dify API 单元测试,执行 test_helpers.py 中的 TestHelpers::test_detect_file_encodings。该测试会写入一个小文本文件并检测其编码,预期在生产 helper 中重新打开该路径。Linux/macOS 上可通过,Windows 上失败。
报错原文
[Bug] test_detect_file_encodings fails on Windows: cannot reopen an open NamedTemporaryFile
PermissionError: [Errno 13] Permission denied: 'C:\\Users\\...\\Temp\\tmpxxx.txt'
原因分析
最可能原因:测试在 with tempfile.NamedTemporaryFile(mode="w+t") as temp 块内、文件仍处于打开状态时调用 detect_file_encodings(temp_path)。该 helper 内部使用 charset_normalizer.from_path() 重新打开文件,而 Windows 上同一 NamedTemporaryFile 在关闭前无法被另一个句柄重新打开(平台差异,已有文档说明),因此触发 PermissionError。这是测试代码的可移植性 bug,不是生产逻辑错误。
环境排查
- 确认操作系统为 Windows,且测试在本地源码环境下运行。
- 确认 Dify 代码版本接近 Issue 中提到的
main@b6824334cf或 API 1.16.x。 - 确认执行的命令为
uv run --project api pytest api/tests/unit_tests/core/rag/extractor/test_helpers.py::TestHelpers::test_detect_file_encodings。 - 对比同测试在 Linux/macOS 上的结果,用于区分平台差异。
- Python 版本、依赖版本在本 Issue 中未明确,排查时如遇到其他报错再单独记录。
解决步骤
- 打开
api/tests/unit_tests/core/rag/extractor/test_helpers.py,定位test_detect_file_encodings中的NamedTemporaryFile用法。 - 将文件写入与编码检测拆分为两步:在
with块内只写入内容并flush,块退出后文件已关闭,再调用detect_file_encodings(可优先尝试)。 - 创建临时文件时增加
delete=False,并在finally中显式os.unlink(temp_path)清理,避免残留文件(可优先尝试)。 - 保存后重新执行上述 pytest 命令验证。
验证方法
在 Windows 上重新运行 test_detect_file_encodings,不再出现 PermissionError,且断言 len(encodings) == 1、编码属于 utf_8 或 ascii 均通过;同时检查临时目录中没有遗留测试生成的 .txt 文件。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。


