快速结论:当 Dify 使用 DB_TYPE=mysql 部署时,访问 Explore 页面的已安装应用列表(GET /console/api/installed-apps)会因 SQL 中使用了 MySQL 不支持的 NULLS LAST 语法而返回 500,优先排查查询排序语句与 MySQL 兼容性。
适用环境:Dify 使用 MySQL 作为数据库(DB_TYPE=mysql),版本自 1.17.0 起受影响(排序逻辑由 #39739 引入)。Issue 未提供操作系统、Python、CUDA、显卡等环境信息。
最快修复方案:暂无确认的一步修复方案。#41455 曾提出将 .desc().nulls_last() 改为显式 last_used_at.is_(None) 排序键加 last_used_at.desc() 的写法,但该 PR 已关闭、未合并,不应视为可用修复。维护者下一步是参考 #41455 的思路,在 api/repositories/installed_app_repository.py 的 _installed_app_order_by() 新位置重新处理,并保持与游标过滤条件一致。
注意事项:任何自行修改排序逻辑的方案都属于推测性处理,需同时保证置顶优先、最近使用优先、从未使用排最后以及 ID 兜底排序不变;Issue 中并未给出已验证的补丁。
问题场景
用户在 MySQL 部署的 Dify 中打开 Explore 页面时,已安装应用列表无法加载。请求 GET /console/api/installed-apps 返回 HTTP 500,底层 SQL 查询在 MySQL 上执行失败。
报错原文
sqlalchemy.exc.ProgrammingError: (pymysql.err.ProgrammingError) (1064, "You have an error in your SQL syntax ... near 'NULLS LAST, installed_apps.id ASC LIMIT 40 ...'")
原因分析
最可能的原因:排序逻辑中使用了 .desc().nulls_last(),生成包含 NULLS LAST 的 SQL。MySQL 不支持该语法,因此返回错误 1064(语法错误)。该排序由 #39739 引入,导致 1.17.0 之后的版本在 MySQL 部署下均受影响。当前代码中该逻辑位于 api/repositories/installed_app_repository.py 的 _installed_app_order_by(),其游标过滤条件也显式把 NULL 时间戳排在非 NULL 之后,需要与排序保持一致。
环境排查
- 确认 Dify 配置中
DB_TYPE是否为mysql。 - 确认 Dify 版本是否在 1.17.0 及以上(该排序引入后受影响的版本范围)。
- 确认问题出现在 Explore 页面的已安装应用列表请求(
GET /console/api/installed-apps)。 - Issue 未提供其他依赖版本信息,无需自行补充未验证的版本项。
解决步骤
- 定位到
api/repositories/installed_app_repository.py中的_installed_app_order_by()。 - 确认其中是否仍包含
.desc().nulls_last(),这是触发 MySQL 1064 的直接来源。 - 参考 #41455 的思路(可优先尝试):将
.desc().nulls_last()替换为显式排序键,即先按last_used_at.is_(None)排序,再按last_used_at.desc()排序,保留原有的 ID 兜底排序。 - 同步检查游标过滤条件中 NULL 时间戳的排序位置,确保过滤与排序顺序一致。
- 由于 #41455 已关闭未合并,且 Issue 中未提供已验证补丁,以上改动需自行测试验证,不要直接套用到生产环境。
验证方法
在 MySQL 部署下重新访问 Explore 页面,确认已安装应用列表可以正常加载,请求 GET /console/api/installed-apps 不再返回 HTTP 500;同时确认列表排序仍满足置顶优先、最近使用优先、从未使用排最后以及 ID 兜底顺序。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。


