
Bug: Redis cache helpers crash on invalid UTF-8 bytes
快速结论:当 Redis 缓存中存储了非 UTF-8 编码的字节数据(例如 b"\xff")时,Dify 的三个缓存助手在 .decode("utf-8") 步骤会抛出 UnicodeDecodeError,导致程序崩溃。优先排查 provider_cache.py、tool_parameter_cache.py、model_provider_cache.py 中 get() 方法的异常处理是否只捕获了 JSONDecodeError 而遗漏了 UnicodeDecodeError。
问题场景
在 Dify 自托管(Self Hosted Source)环境中运行,使用 Redis 作为后端缓存时触发。该问题影响以下三个核心缓存辅助模块:
api/core/helper/provider_cache.pyapi/core/helper/tool_parameter_cache.pyapi/core/helper/model_provider_cache.py
当 Redis 中存储了损坏或非 UTF-8 字节的数据(例如由于数据写入异常、手动修改、或版本升级导致缓存污染),这些缓存的 get() 方法会在调用 .decode("utf-8") 后立即抛出 UnicodeDecodeError,而不是优雅地返回 None。
报错原文
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
# 触发路径示例(单元级复现):
redis_client.get.return_value = b"\xff"
cache.get()
原因分析
所有三个受影响的缓存助手在 get() 方法的异常处理中,只捕获了 JSONDecodeError,用于处理无法解析的 JSON 数据,但没有捕获 UnicodeDecodeError。
当 Redis 返回非 UTF-8 二进制数据时(例如 b"\xff"),.decode("utf-8") 会先于 json.loads() 执行。由于 UnicodeDecodeError 未被捕获,异常会直接传播到调用方,导致程序崩溃。正确的行为应该是像处理坏 JSON 一样返回 None,让调用方回退到真实数据源。
环境排查
- Dify 版本:main 分支(截止 Issue 关闭时间 2026-07-09)
- 部署方式:Self Hosted (Source)
- Redis 服务:确认是否曾写入过非 UTF-8 数据(例如通过 raw Redis CLI、旧版本缓存、或其他非 Dify 进程)
- Python 版本:检查
str.decode("utf-8")的行为——Python 3 强校验 UTF-8,任何无效字节都会导致UnicodeDecodeError
解决步骤
- 定位三个受影响的文件:
api/core/helper/provider_cache.py、api/core/helper/tool_parameter_cache.py、api/core/helper/model_provider_cache.py。 - 在每个文件的
get()方法中,找到现有的except (JSONDecodeError):或except JSONDecodeError:语句。 - 将
UnicodeDecodeError添加到异常捕获列表中,修改为:
except (JSONDecodeError, UnicodeDecodeError):
return None
可优先尝试:如果无法立即修改代码,作为临时绕过方案,可以手动清除 Redis 中对应缓存的 key(例如 DEL <cache_key>),但这不能防止同一问题再次发生。推荐采用代码修复。
验证方法
执行最小单元测试来验证修复:
# 假设已有 mock 的 redis_client
redis_client.get.return_value = b"\xff"
result = cache.get()
assert result is None # 修复后应返回 None,而非抛出异常
或者在 Dify 运行环境中,通过 Redis CLI 手动将一个缓存的值设置为无效字节(例如 SET <some_cache_key> \xff),然后触发相关业务逻辑(如模型配置加载、工具参数获取、提供者缓存刷新),观察是否不再崩溃而是正常回退。
参考来源
langgenius/dify #37834 – Bug: Redis cache helpers crash on invalid UTF-8 bytes



