快速结论:这个报错通常出现在用 OpenAPI 规范生成 SDK 客户端时,某些 schema 把 metadata、config、modelParameters 等字段声明为 object(带 additionalProperties: true),而另一些 schema 又完全没有声明 type,导致生成器把它们退化成语言顶层类型(Java 的 Object、TypeScript 的 any、Go 的 interface{})。优先排查你依赖的那个 schema 里字段是否确实缺失 type,以及它是请求侧还是读取侧字段。
适用环境:Langfuse 公共 API 的 OpenAPI 规范及基于它生成的 SDK 客户端;Issue 中针对的部署副本统计日期为 2026-09-18。未提供操作系统、Python、CUDA、显卡或依赖版本信息。
最快修复方案:暂无确认的一步修复方案。该问题本质是规范层面的一致性问题,Issue 中明确说明请求侧的 metadata/config 属于“当前大版本内不修改”的范围,读取侧的修复已随 #18122、#17892 合并,需要升级到包含这些改动的版本才能拿到修正后的类型。
注意事项:不要自行把未声明 type 的字段一律改成 type: object——Issue 维护者指出请求侧这些字段运行时接受任意 JSON 值(字符串、数字、布尔、数组、对象),强行收窄为 object 会让规范拒绝 API 实际接受的载荷,并导致严格生成客户端(Java/Go)反序列化失败。真正该修的是 inputSchema/expectedOutputSchema 这类运行时确实校验为 JSON 对象的字段。
问题场景
使用 Langfuse 公共 API 的 OpenAPI 规范生成强类型 SDK 客户端(Java、Go、TypeScript 等)时,调用方发现同一个概念字段在不同 schema 里的静态类型不一致:某些 schema 声明为对象,另一些 schema 则完全没有 type,生成结果退化成顶层类型。受影响字段集中在 metadata、config、modelParameters,以及 OtelSpan 中的若干标量字段。
Issue 中统计:未声明 type 的属性共 56 个,其中 29 个属于对象类字段、5 个属于标量字段、22 个是合法的任意 JSON(不应修改)。另有 28 个组合 schema(通过 allOf/oneOf 组合)会继承这些问题。
报错原文
metadata, config and modelParameters are typed as objects in some schemas and untyped in others
规范中表现为同一字段名在不同 schema 下类型声明不一致,例如:
# 已正确声明
metadata:
type: object
additionalProperties: true
# 未声明 type(在 OpenAPI 3.0 中等于 any type)
metadata:
description: ...
原因分析
最可能的原因是部分字段在编写 OpenAPI 规范时遗漏了 type 声明。在 OpenAPI 3.0 中,缺失 type 表示“任意类型”,代码生成器会输出对应语言的顶层类型:Java 为 Object、TypeScript 为 any、Go 为 interface{},调用方拿不到任何编译期约束,只能手动判型和强制转换。
但 Issue 维护者给出了反向视角:对于 metadata、config、modelParameters,未声明 type 的版本反而是正确的。服务端运行时校验接受字符串、数字、布尔、数组、对象等任意 JSON 值(摄入示例里甚至发送过 metadata: "My metadata"),因此把这些字段收紧为 object 会让规范拒绝 API 实际接受的载荷,并破坏严格生成客户端。真正“格格不入”的是那些已经把它们收窄为 map 的 schema(scores、experiments、llm-connections)。
而 OtelSpan 中的 traceId、spanId、parentSpanId、startTimeUnixNano、endTimeUnixNano 属于另一类问题:描述明确说是十六进制字符串或纳秒整数,但同一 schema 内相邻的 name、kind、attributes 都已声明类型,这五个却没有,看起来是遗漏。
环境排查
- 确认你使用的 Langfuse 版本是否包含 #17892 和 #18122 的改动(OtelSpan 标量、dataset inputSchema/expectedOutputSchema、读取侧 metadata 的修复)。
- 确认报错/类型丢失的字段属于请求侧还是读取侧:请求侧
metadata/config在当前大版本内不会收窄;读取侧的metadata(Trace、Observation、ObservationV2、BaseScore、BaseScoreV1)已改为 map。 - 确认你生成的客户端是否开启了严格反序列化(strict deserialization):读取侧 dataset / dataset item / dataset run 的
metadata、prompt 的config/lastConfig、model 的tokenizerConfig、observation 的modelParameters目前仍是按存储原样返回,可能为字符串等非对象值,严格客户端会反序列化失败。 - 确认
status(OtelSpan)字段:其描述自称 “Span status object”,但当前未声明类型。
解决步骤
- 先区分字段类别,不要做一刀切修改。按 Issue 建议分为:对象类无类型(29 个)、标量无类型(5 个)、合法的任意 JSON(22 个,不应改动)。
- 对
OtelSpan的五个标量(traceId、spanId、parentSpanId、startTimeUnixNano、endTimeUnixNano),补上对应标量类型;这部分属于已合并的 #17892 修复范围,升级即可获得。 - 对 dataset 的
inputSchema/expectedOutputSchema,补上对象类型;这部分同样在 #17892 中修复,因为运行时确实将它们校验为 JSON 对象。 - 对读取侧的
metadata(Trace、Observation、ObservationV2、BaseScore、BaseScoreV1 及其组合 schema),#18122 已将其改为 map,升级到包含该改动的版本即可,无需单独修改组合 schema。 - 对请求侧的
metadata/config(摄入 body、dataset 与 prompt 创建请求),以及读取侧的 dataset/dataset item/dataset runmetadata、promptconfig/lastConfig、modeltokenizerConfig、observationmodelParameters,当前大版本内不要收窄类型;这些将在下一个大版本中随旧摄入端点移除一并规范化。 - 如果在生成客户端侧临时规避,可优先尝试为这些字段启用语言层面的宽松反序列化(如 Java 的
Object/JsonNode、Go 的json.RawMessage),但这属于客户端侧变通,不代表规范已修复。
验证方法
重新生成 SDK 客户端后,检查目标字段的生成类型是否已从顶层类型(Object/any/interface{})变为具体类型:OtelSpan 的标量应为 string/integer,dataset 的 inputSchema/expectedOutputSchema 应为对象,读取侧 metadata 应为 map/字典结构。同时用一个包含非对象 metadata 值的请求验证 API 仍能正常接受,确认没有因类型收窄而误拒合法载荷。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。


