快速结论:这个报错通常出现在用不存在的 public key 访问 Langfuse 公共 API(如 /api/public/projects)时,服务端 logger.error("No key found for public key", publicKey) 中的 publicKey 参数被 winston 丢弃,日志只剩通用文案,无法定位是哪个 key 被拒绝。优先排查日志格式链是否缺少 winston.format.splat(),以及该调用是否用了字符串作为第二个参数。
适用环境:Langfuse 自托管部署(langfuse-web 服务);日志使用 winston(Issue 隔离复现基于 winston 3.19.0,处于 packages/shared 锁定的 ^3.15.0 范围内);同时覆盖 LANGFUSE_LOG_FORMAT=text 与默认 JSON 两种日志格式。Issue 未提供操作系统、Python、CUDA、显卡等信息。
最快修复方案:暂无确认的一步修复方案。Issue 中的维护者确认已复现该问题,并给出修改建议(将字符串插值进日志消息,而不是作为第二个参数传入),但截至 Issue 关闭时没有合并已验证的补丁。
注意事项:建议修复方案来自维护者在讨论中的回复,属于建议性质,未在官方版本中验证;自行改动 apiAuth.ts 属于本地补丁,升级 Langfuse 时需重新检查。此外把 public key 明文写入日志本身涉及信息暴露,落地时需评估日志访问权限。
问题场景
在自托管的 Langfuse 实例上,用不存在的 Basic auth 凭据调用任意公共 API 端点,例如:
curl -s -u "pk-lf-does-not-exist:sk-lf-does-not-exist" https://<host>/api/public/projects
此时查看 langfuse-web 日志,只能看到 error No key found for public key,看不到被拒绝的 public key 具体是什么。对于重复请求,服务端在 API_KEY_NON_EXISTENT 负缓存路径上直接短路,除通用的 Error verifying auth header: Invalid credentials 外不再产生任何额外信号。
报错原文
error No key found for public key
对应的源码调用(Issue 中引用的 apiAuth.ts):
logger.error("No key found for public key", publicKey);
Issue 标题中的核心英文报错:
bug: public key is dropped from the "No key found for public key" log line
原因分析
Issue 正文和维护者回复都确认了根因:publicKey 是字符串,winston 会把非对象的第二个参数路由到 SPLAT 符号,而不是合并进 info 对象。
packages/shared/src/server/logger.ts的格式链(text 与 json 两条路径)中都没有winston.format.splat()。- 日志消息里也没有
%s占位符。
因此该值在两种格式下都不会出现在输出中:
LANGFUSE_LOG_FORMAT=text:printf只输出timestamp、level、message(以及stack),丢弃所有元数据。- 默认 JSON:
winston.format.json()只序列化可枚举的字符串键,而SPLAT是 symbol。
对照之下,同一文件中错误密钥(public key 存在但 secret 不匹配)的分支使用了模板字符串插值,能正常打出 key:
logger.debug(`Old key is invalid: ${publicKey}`);
同样调用形态在 apiAuth.ts 中还出现三处,丢弃的值相同:logger.info("No project id found for key", publicKey)、logger.error("Invalid plan type for key", finalApiKey.plan)、logger.info("No api key found for public key:", publicKey)。(维护者在当前 main 上定位到的对应行为 L126、L164、L171、L284。)而 logger.error("...", error) 这类调用传入的是 Error 对象,winston 能正常合并,并由 format.errors({ stack: true }) 打出堆栈,不受此问题影响。
环境排查
- 确认 Langfuse 部署方式:自托管,涉及
langfuse-web服务。 - 确认日志格式:
LANGFUSE_LOG_FORMAT=text还是默认 JSON;两种格式下该问题都存在,需确认自己看的是哪条格式链。 - 确认产品版本/代码版本:Issue 讨论基于
maincommit471e150a,正文引用行为apiAuth.tsL116/L154/L161/L314,维护者在 main 上定位为 L126/L164/L171/L284,行号随版本漂移,需以实际版本为准。 - 确认 winston 版本:Issue 隔离复现使用 3.19.0,处于
packages/shared锁定的^3.15.0范围内。 - 确认
packages/shared/src/server/logger.ts的格式链中是否存在winston.format.splat()。 - 确认是否具备 ingress/代理层请求日志:Issue 指出识别配置错误的客户端通常依赖这一层,而许多自托管部署在该主机上没有。
- Issue 未提供操作系统、Python、CUDA、显卡信息,无需排查。
解决步骤
- 先复现:用不存在的 Basic auth 凭据请求任一公共 API 端点,然后在
langfuse-web日志中确认是否只出现No key found for public key而没有 key 值。 - 定位触发点:在对应版本的
web/src/features/public-api/server/apiAuth.ts中找到logger.error("No key found for public key", publicKey)这一行(Issue 正文为 L116,main471e150a为 L126)。 - 核对日志格式链:检查
packages/shared/src/server/logger.ts中 text 与 json 两条链是否包含winston.format.splat(),并确认消息中没有%s占位符。这是判断根因是否成立的关键。 - 可优先尝试维护者在 Issue 中给出的建议修复:把这四处调用改成字符串插值,与已有的
logger.debug(`Old key is invalid: ${publicKey}`)风格保持一致,例如把logger.error("No key found for public key", publicKey)改为logger.warn(`No key found for public key: ${publicKey}`),并同步处理另外三处(No project id found for key、Invalid plan type for key、No api key found for public key:)。 - 关于日志级别:Issue 讨论认为该场景是未知客户端的 401,不是服务端故障,
warn比error更合适,与已使用info的No api key found for public key:一致。此点同样属于建议,落地前自行评估。 - 改动范围限定在
web/src/features/public-api/server/apiAuth.ts上述若干行;Issue 中称可以据此提 PR,但关闭时并未确认已合并的官方修复。 - 若暂不修改代码,可退而求其次在 ingress/反向代理层开启请求级日志,用请求头中的 public key 反查,弥补应用日志缺失的信息。
验证方法
应用改动后,重新用不存在的凭据调用公共 API:
curl -s -u "pk-lf-does-not-exist:sk-lf-does-not-exist" https://<host>/api/public/projects
在 langfuse-web 日志中应能看到被拒绝的 public key(例如 No key found for public key: pk-lf-does-not-exist)。请在 LANGFUSE_LOG_FORMAT=text 与默认 JSON 两种格式下分别确认,因为 Issue 指出该值在两种格式下都会丢失。若日志中仍未出现 key,说明改动未生效或日志格式链并非预期的那一条,需要回查第 3 步。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。


