![[Bug]: Observation/trace ids used verbatim as S3 object keys; non-S3-safe ids (base64 with '=') fail on MinIO](https://www.chat-gpts.plus/wp-content/uploads/2026/07/14457-de7e06c6.jpg)
[Bug]: Observation/trace ids used verbatim as S3 object keys; non-S3-safe ids (base64 with ‘=’) fail on MinIO
快速结论:该报错发生在 Langfuse 自托管环境使用 MinIO 作为 S3 存储后端,且上游(如 LiteLLM)传入的 observation ID 包含 base64 填充字符 = 时。MinIO 会拒绝包含 = 的对象键,导致事件虽被 200 接受但实际丢失。优先排查上游 ID 中是否包含 = 字符,并检查 safeBlobKeySegment 正则的当前覆盖范围。
问题场景
用户在 Langfuse 自托管部署中,使用 MinIO 作为 S3 对象存储后端,通过 LiteLLM 的 langfuse 回调记录 Responses API 的生成事件。LiteLLM 传入的 observation ID 格式为 resp_<base64url>=(包含 base64 填充字符 =),Langfuse 将其直接用作 S3 对象键的一部分,导致 MinIO 拒绝上传。
报错原文
error Failed to upload JSON to S3 <projectId>/observation/time-..._resp_<base64>=/<uuid>.json Object name contains unsupported characters.
error Failed to upload event to S3
Error: Failed to upload events to blob storage, aborting event processing
原因分析
Langfuse 构建 S3 blob 存储键的格式为 <projectId>/observation/<id>/<uuid>.json,其中 <id> 直接使用客户端提供的 observation ID 而未做转义。PR #14090 引入了 safeBlobKeySegment() 函数,但其禁止字符正则仅为 /[\x00-\x1f/\\]/ —— 只过滤控制字符、正斜杠和反斜杠。base64 填充字符 = 不在禁止集合内,因此通过验证。AWS S3 接受 = 字符,但 MinIO 抛出 XMinioInvalidObjectName 错误,导致上传失败且事件丢失(ingestion POST 已返回 200,但数据未到达 ClickHouse)。
环境排查
- Langfuse v3(langfuse-k8s chart)版本确认
- 存储后端:MinIO 版本确认(AWS S3 不会触发此问题)
- 上游 ID 源:LiteLLM proxy Responses API,ID 格式是否包含
=字符 - 检查
LANGFUSE_S3_EVENT_KEY_MAX_SEGMENT_BYTES配置项(用于控制 ext4 NAME_MAX 长度,但与=问题无关) - 确认 ClickHouse 中无对应 trace 数据
解决步骤
- 确认问题是否为
=字符导致:检查 Langfuse web 日志中的错误对象键,确认包含=字符。 - 等待上游 Langfuse 修复:扩展
safeBlobKeySegment.ts中的禁止字符正则以包含 MinIO 拒绝的字符(至少=),Langfuse 团队已知此问题,hash-suffix 碰撞避免机制已存在,扩展字符集不会破坏现有安全键。 - 临时解决(可优先尝试):在 LiteLLM 端对 observation ID 进行 URL 编码或剥离
=字符,再传入 Langfuse。注意:此方案为临时 Workaround,非长期解决方案。
验证方法
修复后,使用包含 = 字符的 observation ID(如 resp_<base64url>=)触发 trace 事件,检查 Langfuse web 日志中无 Object name contains unsupported characters 错误,且 trace 数据成功出现在 UI 界面。


