快速结论:该报错发生在 Langfuse Python SDK 序列化 pydantic 模型时,当模型内嵌的浮点数为 NaN/Inf 时,会绕过安全转换逻辑,直接输出非法的裸 NaN/Infinity JSON 令牌,导致 ingestion 服务器 JSON.parse 拒绝接收。优先检查 langfuse/_utils/serializer.py 中 BaseModel 分支是否递归调用了 default()。
适用环境:langfuse-python SDK v4.14.x(当前 main 分支),依赖 pydantic 模型。操作系统、Python 版本、CUDA、显卡等环境变量在 Issue 中未提供,无法确认。
最快修复方案:暂无确认的一步修复方案。可优先尝试将 BaseModel 分支的 return obj.model_dump() 改为 return self.default(obj.model_dump()),让序列化结果递归经过 float 安全转换逻辑。
注意事项:此为 Issue 中提出的修复建议,尚未有官方发布版本验证。修改需自行测试,且 dataclass 分支存在相同问题,建议一并处理。该修改涉及核心链路序列化器,改动后需回归测试正常数据流。
问题场景
在 Langfuse Python SDK 的 tracing 核心路径上,span 的 input/output/metadata 通过 langfuse/_client/attributes.py 的 _serialize 方法序列化。当被追踪的 pydantic 对象中嵌套了 NaN/Inf 浮点数(常见于 ML/评分相关的 payload),就会触发此问题。
报错原文
[SDK][Python] NaN/Inf floats nested in a pydantic model serialize to invalid JSON (bare NaN/Infinity)
原因分析
可能原因是 langfuse/_utils/serializer.py 中的 EventSerializer 对不同类型的对象采用了不同的序列化策略:
- dict/list 分支会递归调用
self.default(),因此能触发 float 的 NaN/Inf 安全转换(转换为"NaN"、"Infinity"、"-Infinity"字符串令牌)。 - pydantic BaseModel 分支直接返回
obj.model_dump(),没有递归回default(),导致原始float("nan")直接进入 Python JSON C-encoder,输出裸的NaN/Infinity令牌。 - dataclass 分支(
return asdict(obj))也存在相同问题,未递归处理。
环境排查
- 确认 langfuse-python SDK 版本为 v4.14.x(Issue 中确认的版本)
- 检查 pydantic 模型定义,确认字段类型为 float 且可能赋值为 NaN/Inf
- 确认在使用 span 的 input/output/metadata 参数时传递了包含 NaN/Inf 的 pydantic 对象
解决步骤
- 定位
langfuse/_utils/serializer.py,找到BaseModel分支(当前行号约 132-139)。 - 将
return obj.model_dump()修改为return self.default(obj.model_dump()),使序列化结果递归经过 float 安全转换逻辑。 - 检查 dataclass 分支(
is_dataclass),将return asdict(obj)同样修改为return self.default(asdict(obj)),修复同类问题。 - 如果场景中使用了 pydantic 的
raw属性(嵌套 BaseModel),确保先调用raw.model_rebuild()再递归处理。 - 修改后运行原有的序列化功能,确认输出为合法 JSON。
验证方法
使用 Issue 中的可运行复现脚本验证:
from pydantic import BaseModel
from langfuse._utils.serializer import EventSerializer
class Scores(BaseModel):
confidence: float
encoded = EventSerializer().encode(Scores(confidence=float("nan")))
# 修复后应输出 {"confidence": "NaN"} 而非 {"confidence": NaN}
import json
json.loads(encoded, parse_constant=lambda t: (_ for _ in ()).throw(ValueError(t)))
# 修复后不应抛出 ValueError
同时建议在真实 tracing 流程中发送包含 NaN 的 span 数据,确认 ingestion 服务器能正常接收。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。

![`/config` returns `username` as an unawaited coroutine string (regression from #13749])](https://www.chat-gpts.plus/wp-content/uploads/2026/08/13758-6cb92da7-768x403.jpg)
![[Bug]: DashScope tiered pricing uses graduated slices instead of the request-size tier](https://www.chat-gpts.plus/wp-content/uploads/2026/08/34729-a68deaea-768x403.jpg)